[docker] docker compose

docker compose 是一个简化运行 docker 指令的工具,它可以部分代替 docker build 和 docker run 指令,但是无法取代 docker 指令,更不会取代容器和镜像。它可以运行单个或多个容器,通过运行 YAML 配置好的文件建造镜像和运行容器

不过 docker compose 有个缺点,它无法管理不同 hosts 上的容器——这个需要通过 类似于 docker swarm/kubernetes 这样的工具去进行管理

docker compose 文件

这里不会过多涉及 YAML/YML 的语法,下面分成一个个的 service,每个 service 是在 services 这个 key 下

不包含 service 具体实现的框架如下:

version: "3.8"
services:
  mongodb:
  backend:
  frontend:

volumes:
  data:
  logs:

命名规范——默认为 docker-compose.yaml,运行指令时需要在 docker-compose.yaml 同一个文件夹里运行

mongodb

mongodb:
  # container_name: mongodb
  image: "mongo"
  volumes:
    - data:/data/db
  # environment:
  #   # - MONGO_INITDB_ROOT_USERNAME=root
  #   MONGO_INITDB_ROOT_PASSWORD: root
  #   MONGO_INITDB_ROOT_USERNAME: root
  env_file:
    - ./env/mongo.env

backend

backend:
  # build: ./backend
  build:
    # should be the highest common parent level
    context: ./backend
    # can be omitted if the name is same as Dockerfile
    dockerfile: Dockerfile
  ports:
    - "80:80"
  volumes:
    - logs:/app/logs
    # can use relative path here
    - ./backend:/app
    - /app/node_modules
  env_file:
    - ./env/backend.env
  depends_on:
    - mongodb

frontend

frontend:
  build: ./frontend
  volumes:
    - ./frontend/src:/app/src
  ports:
    - "3000:3000"
  stdin_open: true
  tty: true
  depends_on:
    - backend

运行

讲配置之前先简单的提一下运行

up

安装最新版本的 docker 可以直接通过 docker compoe 去运行,如下面就是直接运行 docker compoe up 的结果:

❯ docker compose up
[+] Running 1/0
 ✔ Container compose-mongodb-1  Created                                                                                                                    0.0s
Attaching to mongodb-1
# will hang here, but can stop using cmd+c
# run detached mode
❯ docker compose up -d
[+] Running 1/1
 ✔ Container compose-mongodb-1  Started                                                                                                                    0.0s
❯ docker compose down
[+] Running 2/2
 ✔ Container compose-mongodb-1  Removed                                                                                                                    0.1s
 ✔ Network compose_default      Removed

默认情况下 docker compoe up 不会在 detached 模式下运行,但是可以直接使用 cmd/ctrl+c 的方式去终结运行。一旦 docker compoe up 被终止,那么所有的容器就会进入终止状态:

[+] Stopping 1/2d with code 0
 ✔ Container compose-frontend-1  Stopped                                                                                                                   0.7s
[+] Stopping 3/3pose-backend-1   Stopping                                                                                                                  0.6s
 ✔ Container compose-frontend-1  Stopped                                                                                                                   0.7s
 ✔ Container compose-backend-1   Stopped                                                                                                                   0.7s
 ✔ Container compose-mongodb-1   Stopped                                                                                                                   0.1s
mongodb-1 exited with code 0
canceled
❯ docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
❯ docker ps -a
CONTAINER ID   IMAGE              COMMAND                  CREATED          STATUS                     PORTS     NAMES
04fd7da5b373   compose-frontend   "docker-entrypoint.s…"   18 seconds ago   Exited (1) 7 seconds ago             compose-frontend-1
9ad9301633bd   compose-backend    "docker-entrypoint.s…"   18 seconds ago   Exited (1) 7 seconds ago             compose-backend-1
72c2fbe335e4   mongo              "docker-entrypoint.s…"   18 seconds ago   Exited (0) 6 seconds ago             compose-mongodb-1
9888e9d4cf74   mysql              "docker-entrypoint.s…"   2 days ago       Exited (0) 2 days ago                mysql

添加 -d flag 可以在 detached 模式下运行 docker compose

down

docker compose down 可以用来终止并清理所有通过 docker-compose.yaml 管理的容器,如:

❯ docker ps -a
CONTAINER ID   IMAGE              COMMAND                  CREATED          STATUS                     PORTS     NAMES
04fd7da5b373   compose-frontend   "docker-entrypoint.s…"   18 seconds ago   Exited (1) 7 seconds ago             compose-frontend-1
9ad9301633bd   compose-backend    "docker-entrypoint.s…"   18 seconds ago   Exited (1) 7 seconds ago             compose-backend-1
72c2fbe335e4   mongo              "docker-entrypoint.s…"   18 seconds ago   Exited (0) 6 seconds ago             compose-mongodb-1
9888e9d4cf74   mysql              "docker-entrypoint.s…"   2 days ago       Exited (0) 2 days ago                mysql
❯ docker compose down
[+] Running 4/4
 ✔ Container compose-frontend-1  Removed                                                                                                                   0.0s
 ✔ Container compose-backend-1   Removed                                                                                                                   0.0s
 ✔ Container compose-mongodb-1   Removed                                                                                                                   0.0s
 ✔ Network compose_default       Removed                                                                                                                   0.1s
❯ docker ps -a
CONTAINER ID   IMAGE     COMMAND                  CREATED      STATUS                  PORTS     NAMES
9888e9d4cf74   mysql     "docker-entrypoint.s…"   2 days ago   Exited (0) 2 days ago             mysql

network

默认情况下所有 docker-compose 中管理的容器都会在同一个 docker network 中,没有特殊需求可以不用配置

build 镜像

默认情况下,如果 docker-compose.yaml 文件中有配置的话,那么 docker compsoe 指令会在找不到所需的镜像这一情况下自动 build

如果想要强制 docker compose 去重新 build 镜像,可以使用 build 这个 arg

❯ docker compose build
[+] Building 1.4s (17/17) FINISHED                                                                                                         docker:desktop-linux
 => [backend internal] load .dockerignore                                                                                                                  0.0s
 => => transferring context: 68B                                                                                                                           0.0s
 => [backend internal] load build definition from Dockerfile                                                                                               0.0s
 => => transferring dockerfile: 202B                                                                                                                       0.0s
 => [frontend internal] load metadata for docker.io/library/node:latest                                                                                    1.1s
 => [frontend 1/5] FROM docker.io/library/node@sha256:162d92c5f1467ad877bf6d8a098d9b04d7303879017a2f3644bfb1de1fc88ff0                                     0.0s
 => [backend internal] load build context                                                                                                                  0.0s
 => => transferring context: 924B                                                                                                                          0.0s
 => CACHED [frontend 2/5] WORKDIR /app                                                                                                                     0.0s
 => CACHED [backend 3/5] COPY package.json .                                                                                                               0.0s
 => CACHED [backend 4/5] RUN npm install                                                                                                                   0.0s
 => CACHED [backend 5/5] COPY . .                                                                                                                          0.0s
 => [backend] exporting to image                                                                                                                           0.0s
 => => exporting layers                                                                                                                                    0.0s
 => => writing image sha256:0b50e06210a6786efef5e4b403eed36760a9fac59a81b75c5b0ba0070918c0e6                                                               0.0s
 => => naming to docker.io/library/compose-backend                                                                                                         0.0s
 => [frontend internal] load build definition from Dockerfile                                                                                              0.0s
 => => transferring dockerfile: 147B                                                                                                                       0.0s
 => [frontend internal] load .dockerignore                                                                                                                 0.0s
 => => transferring context: 70B                                                                                                                           0.0s
 => [frontend internal] load build context                                                                                                                 0.0s
 => => transferring context: 4.31kB                                                                                                                        0.0s
 => CACHED [frontend 3/5] COPY package.json .                                                                                                              0.0s
 => CACHED [frontend 4/5] RUN npm install                                                                                                                  0.0s
 => CACHED [frontend 5/5] COPY . .                                                                                                                         0.0s
 => [frontend] exporting to image                                                                                                                          0.0s
 => => exporting layers                                                                                                                                    0.0s
 => => writing image sha256:98fe0b6f0a0f89aa2c1b36a7a1c54006e5dd0f522209a4d59f2cf768a14c911a                                                               0.0s
 => => naming to docker.io/library/compose-frontend                                                                                                        0.0s

⚠️:docker compose build 不会运行容器,只会重新 build 镜像

配置

接下来补充一下配置的内容

version

这部分可以通过官方文档查看:Compose file versions and upgrading

具体还是要看用的是什么 docker engine,大多数情况下可以使用 3.8,即 docker engine 19.03.0+

目前我的版本是:

❯ docker engine --version
Docker version 24.0.7, build afdd53b

虽然本机上安装的不是最新的版本,不过只差了 3 个 minor 版本,也可以看到大多数情况下用 3.8 就够了

services

services 下面列举的是一个个单独的 service,service 可以理解成容器的具体描述,即一个容器应当如何配置和如何运行

以上面列举的配置为例,mongodb 指的就是当前 service 的名称,并不是容器的名称。比如说 service 的名称是 frontend,但是 docker 容器的名称为 compose-frontend-1

在 docker swarm 的情况下——我们项目用的是 Kubernetes,所以我应该不会设计 swarm,service 指的是不同的东西

volumes

本片配置中,volumes 出现在两个地方,一个和 services 平级,一个在单独的 service 里

和 services 平级的 volumes 是整个 compose 文件中所有出现过的命名卷及其配置——本片配置出现的都是极简配置。和 services 平级的 volumes 并不是强制要求定义的,不过一般来说被认为是个 good practice

在单独的 service 中的 volumes 则是当前容器会使用的 volume,包含 bind mounts,anonymous volume 和 named volume

image

这是在当前 service 使用的是别人已经实现好的 image 的情况下使用

如上面实现的 mongodb,我这里没有 load 其他的数据看不需要额外的 Dockerfile 去实现,所以直接使用 image 即可

build

这是在需要 tailor 别人实现的 image,添加自己的代码

前后端有自己实现的代码,需要运行 Dockerfile 去 build 镜像,这里就会使用 build 去实现

这里的实现方法有两种:

  1. 直接指定 Dockerfile 所在的文件夹地址

    这里可以使用相对路径,所以注释掉的代码用的是 build: ./backend

    这种情况下 compose 会自动寻找该目录下的 Dockerfile 文件去运行

  2. 使用更细节的配置

    这里提到的是 context 和 dockerfile

    context 是当前 container 的作用域,也就是说 Dockerfile 中所有会涉及到的文件——如 COPY 操作所需要的文件都应存在于当前作用域,不然可能会导致 build 失败

    dockerfile 则是 Dockerfile 的名称,默认情况下为 Dockerfile

ports

即端口,可以暴露和 map 多个端口

环境参数

这里实现的方法有两种:

  1. 直接写

    这里也有两种实现方法:

    • - MONGO_INITDB_ROOT_USERNAME=root
    • MONGO_INITDB_ROOT_PASSWORD: root

    二者不可通用

    两个都是 YAML 的语法,这里不多赘述

  2. 配置一个环境变量的文件

    主流还是搭配一个 .env 文件,如 mongo.env 的内容为:

    MONGO_INITDB_ROOT_PASSWORD=root
    MONGO_INITDB_ROOT_USERNAME=root
    

depends_on

这是在有依赖关系的时候使用,如后端项目依赖于 mongodb 实现,那么后端的 depends_on 就是 mongodb

这个会和优先级/排序有关系,可以被依赖的容器存在,但是无法完全保证被依赖的项目一定会初始完毕。要保证被依赖的容器已经成功初始化,可以被连接,还需要使用其他的工具辅助

container_name

容器最终会使用的名称,可选

项目比较小/简单的时候用不用都可以,当然,用了更具有指向性

stdin_open & tty

就是 -it,进入 interact mode 和 teletypewriter

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐