首先要明白 docker 是什么,然后要知道 docker 的一些基本概念,如 image、container、volumes 和 swarm 等。最后就是简单的使用了,我用 wordpress 先做做试验先!

docker 是啥子?

docker 是 linux 容器的一种封装,简单灵活便携,反正很流行就对了。

docker 安装

Ubuntu 下可以直接使用 repository

$ sudo apt-get update

然后安装必要的包,让 apt 包管理支持 https

$ sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg-agent \
    software-properties-common

一路 {ctrl} + {c} & {ctrl} + {v}

$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

$ sudo apt-key fingerprint 0EBFCD88

$ sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"

$ sudo apt-get update

$ sudo apt-get install docker-ce docker-ce-cli containerd.io

安装完毕过后使用 docker version 查看正在运行,使用 sudo service docker restart | start | stop 来管理docker 服务。docker 需要 sudo 权限,为了避免每次使用 sudo,可以把用户加入 docker 用户组

sudo usermod -aG docker $USER

images 、containers 和 volumes

docker 会将所有需要的运行环境和包乃至配置文件、环境变量等一并打包成一个 imagecontainer 则是一个 image 的实例——就是 image 的“现在进行时“。而 volumes 和 images、container 不是一个物种,不过有必要了解一下 volumes 是个什么东西。docker 可以使用3种方式挂载容器内的数据:volumes 、bind mounts 和 tmfs volumes。暂时只关心 volumes 好了,其他的看不懂。

volumes 其实就是 docker 自己管理的卷,用于管理容器生成和容器正在使用的数据。在 linux 系统中一般存放在 /var/lib/docker/volumes 文件夹下。使用 docker create -v ... 可以生成一个绑定了 volume 的容器,如:

docker create -v /data --name data ubuntu

该命令会让 docker 创建一个名字叫做 data 的 container(该 container 是一个叫做 ubuntu 的 image 的实例) ,并且将容器的 /data 文件夹挂载到 docker 的卷管理下(也就是 /var/lib/docker/volumes/data),此时可以使用 docker volume ls 看到 VOLUME NAME 字段是一段加密字符。当然可以使用 named volume 显式设置 VOLUME NAME。

docker create -v test:/data --name data ubuntu

可以看到多 docker volume 的卷管理下面多了一个 test

PS: 如果这个 test 换成绝对路径的话,比如 docker create -v /home/johnny/test:/data –name data ubuntu。此时 /data 会被绑定到宿主机的 /home/johnny/test 文件夹下,而 docker volume ls 就没有 test 了。

那么如何管理 images、containers 和 volumes 呢,增删改查?

docker docker docker 就完事了。。。

docker image --help
docker container --help
docker volume --help

by the way: -prune 参数是一键删除,好用的很:-O

docker hello-world

直接使用 docker container run hello-world 或者 docker run hello-world 就行,docker 会自动从官方仓库 pull hello-world 这个 image 到本地然后运行。试试就行了,反正自动退出的。不过大多容器提供的是服务,不会自动终止。要想终止怎么办,那就crtl + c 弄死就好,优雅一点的可以使用 docker container kill [containID] 这个 命令。哦,containerID 怎么看? –help

使用 docker 搭建 wordpress

想要熟悉一项工具,docs 挨着挨着看——臣妾做不到啊!

用 wordpress 这种简单易用的博客工具来试手再适合不过了,我们开始吧~

自建 wordpress 容器

自己从零建立 wordpress 的话其实和在服务器上搭建的过程一样,这样根本体现不出 docker 带来的优势。不过可以通过这种方式熟悉 docker 的流程。

1.首先是根据 php 的官方镜像来定制自己的镜像

php 官方提供的镜像不一定是即开即用的,有时有时需要自己安装一定的 Extensions。由于 wordpress 的搭建一般采用 mysql 数据库,所以我们需要安装 mysql 扩展。

cd ~
mkdir docker-demo
cd docker-demo
vi Dockerfile

然后在 Dockerfile 中写入以下内容:

FROM php:7.3.0-apache
RUN docker-php-ext-install mysqli
CMD apache2-foreground

最后执行:

#docker build -t [new-image-name] [path]
docker build -t phpwithmysql .

这个 Dockerfile 是什么意思呢?docker build 又是什么意思呢?

意思就是说,我们将要根据 Dockerfile 构建一个新镜像,该镜像继承自 php:7.3.9-apache。Dockerfile 中的每一个指令都会新建立一层,RUN 也不例外,每一个RUN 行为都会在基础上新建一个层,在其上执行完毕后 commit 这一层的修改,构成新的镜像。CMD 指令放在最后,表示构建完毕后启动一个相应的 container 后会运行该命令。
RUN 和 CMD 的区别在于 RUN 指令在 image 文件构建阶段运行,而 CMD 指令在容器启动后运行。一个 Dockerfile 可以有多个 RUN,但是只能有一个 CMD。因此,本地会出现两个镜像,一个是 php:7.3.0-apache 的官方 image,一个是刚新建的 phpwithmysql

2.下载 wordpress 并解压

通过上一个步骤已经构建了一个带有 mysqli 扩展的 php 镜像。接下来可以把 wordpress 的压缩包下载并解压到与 Dockerfile 相同目录了。这里是 docker-demo 目录下

wget https://cn.wordpress.org/latest-zh_CN.tar.gz
tar https://cn.wordpress.org/latest-zh_CN.tar.gz

解压后得到一个 wordpress 文件夹

3.新建一个 mysql 容器

docker container run \
-d \
--rm \
--name wordpressdb \
--env MYSQL_RANDOM_ROOT_PASSWORD='1' \
--env MYSQL_DATABASE=wordpress \
--env MYSQL_USER=wordpress \
--env MYSQL_PASSWORD=12345 \
-p 3306:3306
mysql:5.7

该命令会基于 mysql 5.7 版本的 image 新建一个容器。至于为什么要用 5.7 版本,你完全可以试试用最新版哦,然后自己处理出现的问题吧~

-d 容器期待随后在后台运行
–rm 容器终止后自动删除容器文件
–name 容器的名字叫做什么
–env 传入给容器的环境变量。 MYSQL_DATABASE=wordpress 会使得 mysql 容器会创建一个名字叫 wordpress 的 数据库;MYSQL_USER=wordpress 新建一个 user 叫做 wordpress;MYSQL_PASSWORD=12345 这个名字叫做 wordpress 的新用户密码是12345
-p 将容器的3306(后)端口映射到主机的3306(前)端口

如果命令执行成功,可以查看容器 ID

docker container ls

image

由于使用了端口映射(通常不需要暴露 mysql 的端口,这里只是方便测试),我们可以从外部通过访问主机的3306端口来访问数据库,linux 下可以通过 mysql -uwordpress -p 尝试连接。我这里用的是 workbench。

image

注意:如果使用的 windows 10 insider 的 wsl2 来搭建的 docker 环境,在连接数据库的时候 ip 不是 localhost。可以使用 ifconfig 查看。eth0 段的 ip 就是我们需要的 ip。比如说我的: image

4.新建一个 phpwithmysql 容器

$ docker container run \                                
--rm \
--name wordpress \
--link wordpressdb:mysql \
--volume $PWD/wordpress:/var/www/html \
-p 4000:80 \
phpwithmysql

好了,现在 wordpress 已经可以通过浏览器访问了。我用的 wsl2,所以使用 172.20.28.37:4000 访问,通常使用 localhost:4000

???

建立数据库连接时出错?

image

事情是这个样子的。我们在建立 mysql 容器的时候做了什么事情呢?对了,指定了数据库容器名字是 wordpressdb,指定了数据库名字是 wordpress,指定了数据库用户名叫 wordpress,指定了数据库的用户名密码是12345。想想如果不用 docker 的话怎么搭建的 wordpress 博客……

# 注意我们所有的操作都在 docker-demo 这个文件夹下,从未离开过
vi ./wordpress/wp-config.php

然后配置这些字段

define( 'DB_NAME', 'wordpress' );                                       

/** MySQL数据库用户名 */
define( 'DB_USER', 'wordpress' );

/** MySQL数据库密码 */
define( 'DB_PASSWORD', '12345' );

/** MySQL主机 */
define( 'DB_HOST', '172.20.28.37' ); 

现在再去访问试试

image

使用 wordpress 官方镜像

自己构建一个镜像实在是太原始了,wordpress 提供了官方镜像给我们,所以直接用就好了。保留创建的 mysql:5.7 容器,把 phpwithmysql 容器删除即可。

docker container ls
docker container kill phpwithmysql的容器ID
docker container rm phpwithmysql的容器ID
docker volume --prune 一键删除未使用的卷

然后根据官方的 wordpress 容器定制容器

docker container run \
-d \
--rm \
-p 4000:80 \
--name wordpress \
--env WORDPRESS_DB_HOST=172.20.28.37:3306 \
--env WORDPRESS_DB_USER=wordpress \
--env WORDPRESS_DB_PASSWORD=12345 \
wordpress

由于现在 wsl2 的特殊性,我的 DB_HOST 只能显式设置,不能设置为 127.0.0.1。同时我在构建 mysql 容器的时候也必须把 3306 端口映射出来。
env 中并没有指定 WORDPRESS_DB_NAME,它会自动为 mysql 创建 wordpress 数据库的

或者直接用 –link 就好了

docker container run \
-d \
--rm \
-p 4000:80 \
--name wordpress \
--link wordpressdb:mysql \
--env WORDPRESS_DB_USER=wordpress \
--env WORDPRESS_DB_PASSWORD=12345 \
wordpress

嗯,可以了

使用 docker-compose.yml

上面的情况只有两个容器,一个一个的创建看起来没什么。如果有很多个容器需要关联怎么办呢?一个个创建太麻烦了。还好有 docker-compose。

首先安装 docker-compose,通常情况下 docker-compose 已经和 docker 一起安装了,不过有时候好像不是最新版本。可以使用 pip install docker-compose。然后编辑 docker-compose.yml 文件。

version: '3.7'

    services:
        wordpress:
            image: wordpress
            depends_on:
                - mysql
            volumes:
                - wordpress:/var/www/html
            environment:
                WORDPRESS_DB_HOST: mysql:3306
                WORDPRESS_DB_USER: wordpress
                WORDPRESS_DB_PASSWORD: 12345
                WORDPRESS_DB_NAME: wordpress
            # docker-compose 不支持 deploy,在使用 docker stack deploy 时可以用到
            deploy:
                resources:
                    limits:
                        cpus: "0.5"
            ports:
                - 4000:80
        mysql:
            image: mysql
            volumes: 
                - mysql:/var/lib/mysql
            environment:
                MYSQL_DATABASE: wordpress
                MYSQL_USER: wordpress
                MYSQL_PASSWORD: 12345
                MYSQL_RANDOM_ROOT_PASSWORD: '1'
            ports:
                - 3306:3306

volumes:
    wordpress:
    mysql:

然后运行 docker-compose up 吧!

哦,好像搭建了也没啥用,立即删除!