docker-compose详解

Compose 是用于定义和运行多容器 Docker 应用程序的工具。通过 Compose,您可以使用 YML 文件来配置应用程序需要的所有服务。然后,使用一个命令,就可以从 YML 文件配置中创建并启动所有服务。

基本使用步骤

  • 使用 Dockerfile 定义应用程序的环境。
  • 使用 docker-compose.yml 定义构成应用程序的服务,这样它们可以在隔离环境中一起运行。
  • 最后,执行 docker-compose up 命令来启动并运行整个应用程序。

docker、docker compose的安装参见百度,Dockerfile的书写见上文。

yml 配置指令参考

version

指定本 yml 依从的 compose 哪个版本制定的。

build

使用Dockerfile构建镜像并运行,指定构建镜像的路径。

例如 webapp 服务,指定为从上下文路径 ./dir/Dockerfile 所构建的镜像:

1
2
3
4
version: "3.7"
services:
webapp:
build: ./dir

image

指定容器运行的镜像。以下格式都可以:

1
2
3
4
5
image: redis
image: ubuntu:14.04
image: tutum/influxdb
image: example-registry.com:4000/postgresql
image: a4bc65fd # 镜像id

command

覆盖容器启动的默认命令。等价于Dockerfile的CMD

1
command: ["go", "run", "./main.go"]

container_name

指定自定义容器名称,而不是生成的默认名称。

1
container_name: my-web-container

depends_on

设置依赖关系。

  • docker-compose up :以依赖性顺序启动服务。在以下示例中,先启动 db 和 redis ,才会启动 web。
  • docker-compose up SERVICE :自动包含 SERVICE 的依赖项。在以下示例中,docker-compose up web 还将创建并启动 db 和 redis。
  • docker-compose stop :按依赖关系顺序停止服务。在以下示例中,web 在 db 和 redis 之前停止。
1
2
3
4
5
6
7
8
9
10
11
version: "3.7"
services:
web:
build: .
depends_on:
- db
- redis
redis:
image: redis
db:
image: postgres

注意:web 服务不会等待 redis db 完全启动 之后才启动。

volumes

将主机的数据卷或着文件挂载到容器里。等价于Dockerfile的VOLUME

1
2
3
4
5
6
7
version: "3.7"
services:
db:
image: postgres:latest
volumes:
- "/localhost/postgres.sock:/var/run/postgres/postgres.sock"
- "/localhost/data:/var/lib/postgresql/data"

dns

自定义 DNS 服务器,可以是单个值或列表的多个值。

1
2
3
4
5
dns: 8.8.8.8

dns:
- 8.8.8.8
- 9.9.9.9

entrypoint

覆盖容器默认的 entrypoint。

1
entrypoint: /code/entrypoint.sh

environment

添加环境变量。

1
2
3
environment:
RACK_ENV: development
SHOW: 'true'

expose

暴露端口,但不映射到宿主机,只被连接的服务访问。

1
2
3
expose:
- "3000"
- "8000"

extra_hosts

添加主机名映射。类似 docker client —add-host

1
2
3
extra_hosts:
- "somehost:162.242.195.82"
- "otherhost:50.31.209.229"

tmpfs

在容器内安装一个临时文件系统。

1
tmpfs: /run

networks

配置容器连接的网络,引用顶级 networks 下的条目 。

默认使用myapp_default网络,每个services下的服务以自己名字命名自己的网络加入其中。

自定义网络

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
version: "3"
services:

proxy:
build: ./proxy
networks:
- frontend
app:
build: ./app
networks:
- frontend
- backend
db:
image: postgres
networks:
- backend

networks:
frontend:
# Use a custom driver
driver: custom-driver-1
backend:
# Use a custom driver which takes special options
driver: custom-driver-2
driver_opts:
foo: "1"
bar: "2"

ports

设置容器隐射的端口。等价于 -p 8080:8080

1
2
3
4
5
services:
web:
build: .
ports:
- '8000:8000'

更多信息参考:https://docs.docker.com/compose/gettingstarted/

实例实践

使用docker compose构建一个gin web及其mysql环境。

  1. 创建文件夹

  2. 设计 gin web

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    package main

    import (
    "github.com/gin-gonic/gin"
    "gorm.io/gorm"
    "gorm.io/driver/mysql"
    )

    func main() {
    // 引入GORM
    dsn := "root:123456@tcp(db:3306)/myDB?charset=utf8mb4&parseTime=True&loc=Local"
    db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
    if err != nil {
    panic("failed to connect database")
    }

    // 迁移 schema
    db.AutoMigrate(&User{})

    // Create
    db.Create(&User{UserName: "kid1999", Age: 22})

    // gin 逻辑
    r := gin.Default()
    r.GET("/user/:id", func(c *gin.Context){
    id := c.Param("id")
    user := User{}
    db.First(&user, id)
    c.JSON(200, user)
    })

    r.POST("/user", func(c *gin.Context){
    var u User
    c.Bind(&u)
    db.Create(&u)
    c.JSON(200, u)
    })

    r.Run(":8080")
    }


    type User struct {
    gorm.Model
    UserName string
    Age int64
    }
  3. go 依赖初始化

    1
    go mod init docker-compose
  4. 设计web的Dockerfile

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    From golang:latest

    # 创建文件夹
    RUN mkdir /app

    # 当前工作目录
    WORKDIR /app

    # 将当前文件夹的所有文件复制到容器中
    COPY . /app

    # 设置go代理
    ENV GO111MODULE=on GOPROXY=https://goproxy.io,direct

    # 下载go的依赖
    RUN go mod tidy

    # 暴露端口
    EXPOSE 8080

    # 运行
    CMD go run main.go
  5. 设计docker compose文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    version: "3"

    services:
    db:
    image: "mysql:5.7"
    environment:
    MYSQL_ROOT_PASSWORD: "123456"
    MYSQL_DATABASE: "myDB"
    networks:
    - mynetwork
    ports:
    - "3306:3306"

    web:
    build: .
    ports:
    - "8080:8080"
    networks:
    - mynetwork
    restart: always

    networks:
    mynetwork:

    注意此处有一个大坑,restart: always必须写上,不然会出现mysql创建较慢,导致web连接错误退出的事故!!!

  1. 运行docker compose

    1
    docker-compose up
  2. 关闭所有容器

    1
    docker-compose down