Dokcer Compose 是一个被开发用于帮助定义和分享多容器应用的工具。使用 Docker Compose,我们可以创建一个 YAML 文件去定义服务,使用单一的命令,就可以做好所有事。
使用 Docker Compose 最大的优点在于,你可以用一个文件去定义你的应用,保存在你工程仓库的根目录,可以方便地让别人去给你的工程做贡献。并且,也可以让别人方便地克隆你的仓库,开启 Compose 应用。
安装 Docker Compose
如果你在 Windows 下安装了 Docker Desktop,或者在 Mac 下安装了 Toolbox,你其实已经有了 Docker Compose。如果你使用的是 Linux,你需要去安装 Docker Compose。
安装完之后,你可以运行下面指令来看版本信息。
docker-compose version
创建 Compose 文件
- 在应用工程根目录下,创建文件
docker-compose.yml
。 - 在 compose 文件下,我们从定义架构版本开始。在大部分的案例中,最好使用最新支持的版本。你可以查看 Compose 文件参考 获得当前架构版本和兼容性列表。
version: "3.7"
- 下面,我们将会定义一系列我们应用中想要使用的服务(或容器)。
version: "3.7"
services:
定义应用服务
下面是我们定义应用容器使用的命令。
docker run -dp 3000:3000 \
-w /app -v "$(pwd):/app" \
--network todo-app \
-e MYSQL_HOST=mysql \
-e MYSQL_USER=root \
-e MYSQL_PASSWORD=secret \
-e MYSQL_DB=todos \
node:12-alpine \
sh -c "yarn install && yarn run dev"
- 首先,我们定义服务入口,和容器使用的镜像。我们可以给容器选用任意的名称。名称将会自动成为一个网络别名,这在定义 MySQL 服务时会被使用。
version: "3.7"
services:
app:
image: node:12-alpine
- 典型地,你会看到
image
定义后紧跟着一个command
,虽然没有要求排序。
version: "3.7"
services:
app:
image: node:12-alpine
command: sh -c "yarn install && yarn run dev"
- 下面我们定义端口映射。
version: "3.7"
services:
app:
image: node:12-alpine
command: sh -c "yarn install && yarn run dev"
ports:
- 3000:3000
- 下面我们定义工作目录,和
volume
映射。使用 Docker Composevolume
定义的优势在于,我们可以使用相对路径。
version: "3.7"
services:
app:
image: node:12-alpine
command: sh -c "yarn install && yarn run dev"
ports:
- 3000:3000
working_dir: /app
volumes:
- ./:/app
- 下面定义环境变量。
version: "3.7"
services:
app:
image: node:12-alpine
command: sh -c "yarn install && yarn run dev"
ports:
- 3000:3000
working_dir: /app
volumes:
- ./:/app
environment:
MYSQL_HOST: mysql
MYSQL_USER: root
MYSQL_PASSWORD: secret
MYSQL_DB: todos
定义 MySQL 服务
现在我们开始定义 MySQL 服务,我们给容器使用的命令如下。
docker run -d \
--network todo-app --network-alias mysql \
-v todo-mysql-data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=secret \
-e MYSQL_DATABASE=todos \
mysql:5.7
- 我们首先定义新的服务,然后将他命名为
mysql
。所以它自动获得网络别名。我们接下来明确使用的镜像。
version: "3.7"
services:
app:
# The app service definition
mysql:
image: mysql:5.7
- 下面 ,我们将定义
volume
映射。当我们使用docker run
运行容器时,命名卷被自动创建。当时,当我们运行 Compose 时并不会自动创建。我们需要在顶级volumes:
部分定义volume
,然后在服务配置中明确挂载点。假如只提供volume
名,默认选项被使用。
version: "3.7"
services:
app:
# The app service definition
mysql:
image: mysql:5.7
volumes:
- todo-mysql-data:/var/lib/mysql
volumes:
todo-mysql-data:
- 最后,我们需要确定环境变量。
version: "3.7"
services:
app:
# The app service definition
mysql:
image: mysql:5.7
volumes:
- todo-mysql-data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: todos
volumes:
todo-mysql-data:
到这里,完整的 docker-compose.yml
应该看起来像这样:
version: "3.7"
services:
app:
image: node:12-alpine
command: sh -c "yarn install && yarn run dev"
ports:
- 3000:3000
working_dir: /app
volumes:
- ./:/app
environment:
MYSQL_HOST: mysql
MYSQL_USER: root
MYSQL_PASSWORD: secret
MYSQL_DB: todos
mysql:
image: mysql:5.7
volumes:
- todo-mysql-data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: todos
volumes:
todo-mysql-data:
运行应用栈
现在,我们有了 docker-compose.yml
文件,让我们启动它!
- 确保没有其他 app/db 的复制在运行(
docker ps
和docker rm -f <ids>
)。 - 使用
docker-compose up
启动应用栈。我们添加-d
标签区在后台运行。
docker-compose up -d
运行之后,输出如下:
Creating network "app_default" with the default driver
Creating volume "app_todo-mysql-data" with default driver
Creating app_app_1 ... done
Creating app_mysql_1 ... done
我们发现 Docker Compose 自动为应用栈创建一个网络(这就是为什么我们没在 compose 文件中定义)
3. 使用 docker-compose logs -f
命令查看日志。你可以看到每个服务被交叉进一个单独的流。这对检查时间相关的问题特别有效。-f
标签可以给你生成的实时输出。
mysql_1 | 2019-10-03T03:07:16.083639Z 0 [Note] mysqld: ready for connections.
mysql_1 | Version: '5.7.27' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server (GPL)
app_1 | Connected to mysql db at host mysql
app_1 | Listening on port 3000
在 Docker Dashboard 中观察应用栈
如果我们在 Docker Dashboard中,我们可以看到这有一个被称为 app 的群组。这是 Docker Compose 的工程名称,被用于构成容器的组。默认地,工程名称为 docker-compose.yml
所在目录的目录名。
如果下拉 app,你会看见有两个容器被定义在 compose 文件中。名称是具有描述性的,<工程名称>_<服务名称>_<记录号>
。
卸载它
当你准备去卸载时,使用 docker-compose down
,或者在 Docker Dashboard 删除整个应用。容器会被停止,网络会被移除。
移除 volumes
默认地,运行docker-compose down
时,compose 文件里的 named volumes 不会被移除。如果你想移除volumes
,你需要添加--volumes
标签。
Docker Dashboard不会在删除应用栈时移除volumes
。