共计 5235 个字符,预计需要花费 14 分钟才能阅读完成。
Docker Compose 定义服务之间的关系,很方便地管理多个容器的生命周期。你可以使用 docker-compose.yml 配置文件定义服务之间的关系,然后通过命令行来管理配置文件中定义的服务的生命周期,一般用在开发、测试环境。
docker-compose.yml
docker-compose.yml 描述容器的运行状态,包含了运行服务的容器的配置信息,容器之间的网络交互,挂载文件夹等。使用 yaml 格式,具体的语法可以查看 wiki 上的介绍。
下面是一个 docker-compose.yml 文件的示例:
version: '2'
services:
web:
build: .
depends_on:
- db
- redis
redis:
image: redis
db:
image: postgres
第一行一般标识这个配置文件的语法是哪个版本的,不同的版本对应的支持不同的 Docker Engine 版本,现在最新版本是 3.x。1.x 版本中,每个顶级节点为服务名称,次级节点则为服务容器的配置信息。在 2.x 之后所有的服务都必须定义在 services 节点下面,2.x 支持 Compose 1.6.0 以上的版本,并且 Docker Engine 需要 1.10.0 以上的版本。3.x 主要是与 Docker Engine 的 swarm 模式兼容。不同版本之间的区别、升级指南可以在 官方文档 中查看。
服务的配置项里主要有:build、environment、image、networks、ports、volumes 等,想了解更多可查看 官方文档。
docker compose 相关命令
通过 docker-compose 命令行能方便地构建服务、管理服务的生命周期、查看日志等操作。
docker-compose build // 构建服务镜像
如果服务的 Dockerfile 有更改或者 build 目录里有文件修改,那么会重新构建服务镜像。
下面来做个简单的示例:通过 docker-compose 管理一个 php cli server。项目的根目录是 phpcli:
phpcli/
├── docker-compose.yml
└── web
├── Dockerfile
└── src
└── index.php
web 目录里有个 Dockerfile 描述如何构建这个服务,web 服务的代码都放在 web/src 目录下。
<?php
echo 'hello world';
index.php 里面的文件内容。
docker-compose.yml 文件里面指定使用配置版本是 3 ,services 里定义了一个 php-cli-server 服务,build 项包含了构建容器时的配置信息,这里 ./web
是构建容器的上下文,volumes 指定挂载的目录, ports 指定服务暴露的端口。
version: '3'
services:
php-cli-server:
build: ./web
volumes:
- ./web/src:/var/www/social
ports:
- 8080:8000
当我们运行完 docker-compose build
命令完之后再运行 docker images
会发现生成了一个新的镜像 phpcli_php-cli-server。镜像的命名规则为 project_service,project 默认是目录名,你也可以通过 -p
或--project-name
选项指定项目名。你也可以使用 image 来指定要构建的服务容器名。
现在我们可以通过下面的命令启动服务
docker-compose up // 创建并启动容器
控制台输出:
Creating network "phpcli_default" with the default driver
Creating phpcli_php-cli-server_1 ...
Creating phpcli_php-cli-server_1 ... done
Attaching to phpcli_php-cli-server_1
php-cli-server_1 | PHP 7.1.8 Development Server started at Fri Aug 18 06:12:05 2017
从上面我们可以看到,docker compse 会先创建一个默认的网络 phpcli_default , 可以通过 docker network ls
看到这个新创建的网络。
NETWORK ID NAME DRIVER SCOPE
52b806c648eb phpcli_default bridge local
接着会创建并启动一个以 phpcli_php-cli-server 为镜像的容器,并加入到上面创建的网络中,最后 attach 到容器的控制台,所有容器中的输出会打印在控制台上。现在你可以通过浏览器访问这个 web server 了。一般你可以使用 -d
选项让 docker compose 以后台服务的方式运行项目。
docker-compose logs
Attaching to phpcli_php-cli-server_1
php-cli-server_1 | PHP 7.1.8 Development Server started at Fri Aug 18 06:30:28 2017
php-cli-server_1 | [Fri Aug 18 06:30:40 2017] 192.168.10.1:57739 [200]: /
php-cli-server_1 | PHP 7.1.8 Development Server started at Fri Aug 18 06:31:35 2017
php-cli-server_1 | [Fri Aug 18 06:33:36 2017] 192.168.10.1:57754 [200]: /
可以查看所有容器中产生的日志,每条日志前面会有日志产生的容器的名称。-f
跟 linux tail 命令的 -f
选项相似,可以持续的输出最新的日志。--tail
可以指定输出最近的日志条数,默认为 all ,例如 --tail=10
会打印出所有容器中最近的 10 条日志。
docker-compose stop
停止正在运行的容器,但不会删除容器。可以通过 docker compose start
再次启动服务。
docker-compose start
启动已经存在的服务容器
docker-compose ps
Name Command State Ports
-----------------------------------------------------------------------------------------
phpcli_php-cli-server_1 docker-php-entrypoint php ... Up 0.0.0.0:8080->8000/tcp
列出所有容器的状态,正在运行的命令,端口映射信息。
docker-compose rm
删除已停止的服务容器。
docker-compose port [options] SERVICE PRIVATE_PORT
打印某个服务容器中的端口对外映射的端口号。例如:docker-compose port php-cli-server 8000
会打印出0.0.0.0:8080
。
docker-compose pause
暂停某个服务的正在运行的容器,你可以在之后使用 docker-compose unpause
命令恢复暂停的服务。
docker-compose exec [options] SERVICE COMMAND [ARGS...]
在某个服务容器中运行命令,与 docker exec -it
相似,默认情况下会自动分配一个 TTY 终端。
docker-compose down
停止所有的容器并删除网络、挂载点、构建时生成的镜像。--rmi local
也会删除项目中定义的服务镜像,-v
删除所有命名的、匿名的挂载点。
下面介绍如何 cli server 如何从 mysql 数据库中读取数据:首先在 services 节点下定义一个 db 服务,db 使用 mysql 镜像,并且设置了环境变量 MYSQL_ALLOW_EMPTY_PASSWORD,允许用空密码登录,在开发环境中简单方便:
db:
image: mysql:5.7
ports:
- 3306:3306
volumes:
- ./db/data:/var/lib/mysql
- ./db/sql:/data/sql
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
并对原先的 php-cli-server 服务进行了修改:
php-cli-server:
build: ./web
image: "cli-server"
volumes:
- ./web/src:/var/www/social
ports:
- 8080:8000
depends_on:
- db
depends_on 会在 docker-compose up
的时候会按依赖次序来启动服务,db 服务会在 php-cli-server 服务之前启动,而且在 docker-compose up php-cli-server
也会创建(如果容器不存在)并启动 db 服务。
由于 php:7.1-alpine 镜像中默认没有安装 mysql 扩展,所以需要在 web/Dockerfile 中增加RUN docker-php-ext-install pdo_mysql
。
导入数据库:首先执行 docker-compose exec db /bin/bash
, 进入 mysql 服务容器终端,然后执行mysql -u root -p < /data/sql/social.sql
导入数据(root 用户密码为空)。
修改 web/src/index.php 文件:
$db = new PDO('mysql:host=db;dbname=social;charset=utf8mb4', 'root', '', [PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
]);
$stmt = $db->query("SELECT * FROM posts");
foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $post) {var_dump($post);
}
现在我们可以打开浏览器查看数据库里面的数据了。
到现在为止我们完成了 php 与 mysql 的交互,一般情况下我们都会使用 nginx,那如何让 php 与 nginx 交互呢?我们先通过 docker-compose down --rmi local -v
停止并删除项目中的服务,并移除构建的本地镜像,删除挂载数据信息。
首先得添加 nginx 服务:
nginx:
image: nginx:latest
ports:
- 8080:80
volumes:
- ./web/src:/var/www/social
- ./nginx/conf/social.conf:/etc/nginx/conf.d/social.conf
depends_on:
- web
删除前面的 php-cli-server 服务的定义,这次使用 php-fpm 来做 web 服务,把 web 目录下 Dockerfile 中的基础镜像改成 php:fpm,在 docker-compose.yml 中添加下面的 web 服务。
web:
build: ./web
volumes:
- ./web/src:/var/www/social
ports:
- 9000
depends_on:
- db
下面是 social.conf 文件里的配置信息,其中 fastcgi_pass web:9000;
中的 web 是 docker-compose.yml 中定义的 web 服务的容器地址。
server {
index index.php index.html;
server_name social.local;
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
root /var/www/social;
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass web:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}
然后根据上面的命令,数据库中重新导入数据,然后在宿主机的 hosts 中加入 127.0.1.1 social.local
。通过浏览器访问http://social.local:8080 就可以查看数据了。
我们了解了 Docker compose 的基本用法,也实现了如何搭建一个 lnmp 的 docker 开发环境。