前面讲过Docker Compose的概念,如何安装、以及常用指令等。
这里重点介绍Docker Compose的语法,如何写一个正确的docker-compose.yml文件。
我们知道docker-compose指令(比如docker-compose up等)是运行它的脚本文件docker-compose.yml,那么docker-compose.yml内部到底有哪些语法要求呢!
docker-compose.yml文件是Docker Compose的核心,用于定义服务、网络和数据卷。
该文件使用YAML格式编写,其默认路径为./docker-compose.yml,可以使用.yml或.yaml作为文件扩展名。在docker-compose.yml文件中,可以定义多个服务,每个服务可以包含一系列配置选项,例如镜像名称、容器端口、环境变量等。
此外,docker-compose.yml文件还可以定义网络和数据卷,以便在多个容器之间共享网络和数据。网络可以设置为公共或私有,数据卷可以设置为持久化或非持久化。
使用Docker Compose的基本步骤如下:
Compose 文件是一个 YAML 文件,用于定义 Docker 应用程序的多个容器化服务。这个文件通常用于定义服务、网络、卷、配置和秘密等。
docker-compose.yml文件有以下6个顶级元素:
这些配置项使 Docker Compose 成为一个功能强大的工具,用于定义、部署和管理复杂的 Docker 应用程序。
version 指定Docker Compose文件的版本。目前最新的版本是3。
参考 https://docs.docker.com/compose/compose-file/04-version-and-name/
参考 https://docs.docker.com/compose/compose-file/05-services/
services 定义各个服务。每个服务都有一个唯一的名称,并且需要指定使用的镜像、端口映射、环境变量等信息。并包含以下属性
指定服务所使用的Docker镜像。
image: redis image: redis:5 image: redis@sha256:0ed5d5928d4737458944eb604cc8509e245c3e19d02ad83935398bc4b991aac7 image: library/redis image: docker.io/library/redis image: my_private.registry:5000/redis
参考 https://docs.docker.com/compose/compose-file/build/
指定Dockerfile的路径,用于构建自定义镜像。
build 选项可以接受不同的参数,其中最常用的是 context 和 dockerfile。
以下是一些常见的使用方法:
1)指定构建上下文(context):
构建上下文是一个目录,包含了用于构建镜像的所有文件。当使用 build 选项时,Docker 会将该目录下的所有文件和子目录复制到 Docker 守护进程中,并在那里构建镜像。
services: myservice: build: context: .
在上面的例子中,当前目录(.)被用作构建上下文。这意味着 Docker 将复制当前目录下的所有文件和子目录到 Docker 守护进程中,并在那里构建镜像。
2)指定 Dockerfile:
dockerfile 参数用于指定 Dockerfile 的位置。Dockerfile 是一个文本文件,其中包含了一系列指令,用于定义如何构建 Docker 镜像。
services: myservice: build: dockerfile: ./path/to/Dockerfile
在上面的例子中,Docker 将使用位于 ./path/to/Dockerfile 的 Dockerfile 来构建镜像。
3)使用 Dockerfile 和构建上下文:
当你同时指定 context 和 dockerfile 时,context 是 Dockerfile 的位置的相对路径。这允许你在同一个构建上下文中使用多个 Dockerfile。
services: myservice: build: context: ./path/to/context dockerfile: ./path/to/Dockerfile
在上面的例子中,Docker 将使用位于 ./path/to/context/path/to/Dockerfile 的 Dockerfile 来构建镜像。
4)使用其他构建选项:
除了 context 和 dockerfile 外,build 选项还可以接受其他一些参数,例如 args(用于传递构建参数),target(用于指定 Dockerfile 中的目标),等等。这些参数可以根据需要进行配置。
args 定义构建参数,即 Dockerfile 中的 ARG 值。
以以下 Dockerfile 为例:
ARG GIT_COMMIT RUN echo "Based on commit: $GIT_COMMIT"
在 Compose 文件的 build 键下,可以使用 args 来定义 GIT_COMMIT。args 可以作为 map 或 list 进行设置:
build: context: . args: GIT_COMMIT: cdc3b19
build: context: . args: - GIT_COMMIT=cdc3b19
在指定构建参数时,可以省略值。在这种情况下,构建时间必须通过用户交互获取其值,否则在构建 Docker 镜像时将无法设置构建参数。
args: - GIT_COMMIT
5)使用自定义名称:
你可以为构建的镜像指定一个自定义名称。默认情况下,镜像名称与服务的名称相同,但你可以通过设置 image 参数来覆盖默认名称。
services: frontend: image: example/webapp build: ./webapp backend: image: example/database build: context: backend dockerfile: ../backend.Dockerfile custom: build: ~/custom
指定服务的端口映射。
ports 不能与 network_mode: host 一起使用,否则会出现运行时错误。
Docker Compose中的ports配置项有两种语法格式:短语法和长语法。
1)短语法,比较常见
[HOST:]CONTAINER[/PROTOCOL]
- HOST :[IP:](port | range)
- CONTAINER: port | range
- PROTOCOL:将端口限制为指定协议。如 TCP和UDP
如果主机IP未设置,它将绑定到所有网络接口。端口可以是单个值或范围。主机和容器必须使用等效的范围。
要么指定两个端口(HOST:CONTAINER),要么只指定容器端口。在后一种情况下,Compose会自动分配主机上的任何未分配端口。
HOST:CONTAINER应始终作为(带引号的)字符串指定,以避免与yaml基数-60浮点数发生冲突。
ports: - "9200:9200" - "9300:9300"
2)长语法格式
长语法可以实现短语法无法实现的功能,配置项如下:
ports: - target: 9200 published: 9200 protocol: tcp mode: host - target: 9300 published: 9300 protocol: tcp mode: host
定义服务容器所连接的网络,关联到顶级networks的配置。
services: some-service: networks: - some-network - other-network
指定服务的卷挂载。
卷(volumes)定义了可由服务容器访问的主机路径或命名卷。您可以使用volumes来定义多种类型的挂载,如 volume, bind, tmpfs, 或 npipe。
如果挂载是主机路径并且仅由单个服务使用,则可以在服务定义中声明它。要在多个服务之间重复使用卷,必须在顶级 volumes 键中声明一个命名卷。
以下示例显示了由后端服务使用的命名卷(db-data),以及为单个服务定义的绑定挂载。
services: backend: image: example/backend volumes: - type: volume source: db-data target: /data volume: nocopy: true - type: bind source: /var/run/postgres/postgres.sock target: /var/run/postgres/postgres.sock volumes: db-data:
1)短语法
使用单个字符串与冒号分隔的值来指定卷挂载(VOLUME:CONTAINER_PATH)或访问模式(VOLUME:CONTAINER_PATH:ACCESS_MODE)。
2)长语法
长语法形式允许配置无法在短语法中表示的其他字段。
指定服务的环境变量。
1)Array 语法:
environment: - VAR1=value1 - VAR2=value2
2)Map 语法
environment: RACK_ENV: development SHOW: "true" USER_INPUT:
定义服务的部署配置。可以设置副本数、更新策略等
参考 https://docs.docker.com/compose/compose-file/deploy/
replicas:设置副本数量,默认是1
services: frontend: image: example/webapp ports: - "8080:80" deploy: mode: replicated replicas: 2 endpoint_mode: vip
指定服务依赖的其他服务。
services: web: build: . ports: - "80:80" environment: - ENV=production
command 会覆盖容器镜像声明的默认 command ,例如通过Dockerfile的CMD。
command: bundle exec thin -p 3000
该值也可以是列表,与Dockerfile类似:
command: [ "bundle", "exec", "thin", "-p", "3000" ]
如果值为null,则使用镜像中的默认命令。
如果值为[](空列表)或''(空字符串),则忽略镜像声明的默认命令,即将其覆盖为空。
定义服务的重启策略。可以设置为"no"、“always”、“on-failure"或"unless-stopped”。
restart: "no" restart: always restart: on-failure restart: unless-stopped
networks 定义应用程序使用的网络。可以通过网络名称将不同的服务连接在一起。
Docker Compose Networks 可以不预先创建好网络,默认情况下,这个网络的名字是 “
详细参考 https://docs.docker.com/compose/compose-file/06-networks/
以下是使用 Docker Compose Networks 的基本步骤:
1、使用已有网络
1)创建网络:在开始使用现有网络之前,需要先创建一个 Docker 网络。可以使用以下命令来创建一个网络:
docker network create
2)编写 Docker Compose 文件:接下来,需要编写一个 Docker Compose 文件,来定义服务和网络。在 Compose 文件中,可以定义一个或多个服务,每个服务都可以连接到同一个网络。以下是一个示例的 docker-compose.yml 文件:
version: '3' services: web: image: nginx networks: - my-network db: image: mysql networks: - my-network networks: my-network: external: true
在上述示例中,定义了两个服务,web 和 db。这两个服务都使用同一个网络 my-network。请注意,在 networks 部分,使用了 external: true,表示使用的是现有的外部网络。
2、自动创建网络
不指定external: true,在容器启动的时候,会自动创建网络 “
version: '3' services: web: image: nginx:latest ports: - "80:80" networks: - my-network db: image: mysql:latest ports: - "3306:3306" networks: - my-network networks: my-network: driver: bridge
在上面的示例中,创建了一个名为my-network的自定义网络,并将web和db服务连接到该网络。使用driver参数可以指定网络的驱动程序,默认为bridge。
Docker的网络驱动程序有bridge、host、overlay、macvlan等几种,每种驱动程序都有其特点和应用场景。
每种网络驱动程序都有其适用的场景,可以根据具体的需求选择不同的网络驱动程序来实现不同的容器网络配置。
volumes 定义应用程序的卷。可以创建卷,并将其挂载到服务中。
Docker Compose 中使用数据卷(Volumes)可以通过 volumes 关键字在服务定义中进行指定。
详细参考:https://docs.docker.com/compose/compose-file/07-volumes/
具体用法如下:
在 docker-compose.yml 文件中,针对要使用数据卷的服务,添加 volumes 配置块。例如:
version: "3" services: web: image: nginx volumes: - ./app:/app
在上面的示例中,我们定义了一个名为 web 的服务,使用 image 关键字指定了镜像 nginx。然后通过 volumes 关键字将宿主机目录 ./app 挂载到容器内的 /app 目录上。
另外,如果需要在服务中定义卷标(Volume),可以使用 - 开头的短横线表示卷标名称。例如:
version: "3" services: web: image: nginx volumes: - data:/var/lib/nginx volumes: data:
在上面的示例中,我们定义了一个名为 data 的卷标,并将其挂载到容器内的 /var/lib/nginx 目录上。这样,容器内的 /var/lib/nginx 目录将持久化存储在名为 data 的卷标中。
环境变量文件 .env 用于定义应用程序所需的环境变量。这些环境变量可以在 docker-compose.yml 文件中引用,以配置容器的行为。
默认情况下,.env文件必须和 docker-compose.yml文件在同一个目录中。也可以使用env_file指定文件。
env_file: .env
将 Docker Compose 和环境变量文件 .env 结合使用,可以让你更方便地管理和配置应用程序的环境。以下是一些步骤,说明如何结合使用这两个工具:
DATABASE_URL=postgres://user:password@localhost/dbname SECRET_KEY=my-secret-key
version: '3' services: web: image: my-web-app ports: - "8080:80" environment: - DATABASE_URL=${DATABASE_URL} - SECRET_KEY=${SECRET_KEY}
在上面的示例中,${DATABASE_URL} 和 ${SECRET_KEY} 是对 .env 文件中定义的变量的引用。Docker Compose 会自动将这些值填充到容器的环境变量中。
通过这种方式,你可以轻松地管理和配置应用程序的环境,同时利用 Docker Compose 的功能来简化容器化应用程序的部署和管理。
以下是一个简单的 docker-compose.yml 示例,它创建并运行一个基于 Nginx 的 web 服务器和一个基于 Redis 的数据库:
version: '3' services: web: image: nginx:alpine ports: - "8080:80" volumes: - ./nginx.conf:/etc/nginx/nginx.conf networks: - app-net command: ["nginx", "-g", "daemon off;"] redis: image: redis:latest networks: - app-net command: ["redis-server"] networks: app-net:
这个 docker-compose.yml 文件定义了两个服务:web 和 redis。每个服务都有自己的配置。
你可以根据需要修改这个文件来适应你的应用和环境。例如,你可能需要安装不同的软件或挂载不同的卷,这都可以在服务配置中完成。
以下是一个基于 Spring Boot 项目的 docker-compose.yml 示例:
version: '3' services: backend: build: context: ./backend/ dockerfile: Dockerfile image: backend:latest ports: - "8080:8080" networks: - app-net environment: - spring-boot-app-port=8080 frontend: image: frontend:latest networks: - app-net ports: - "80:80" environment: - FRONTEND_URL=http://backend:8080/ networks: app-net:
这个 docker-compose.yml 文件定义了两个服务:后端(backend)和前端(frontend)。
请注意,你需要根据你的项目结构和需求进行相应的修改。例如,你可能需要修改端口映射、环境变量或网络配置。此外,你还需要确保你的 Spring Boot 项目已经正确配置并能够运行。