1.创建 Compose 项目目录并将当前目录切换到该目录
[root@host1 ~]# mkdir multi-test && cd multi-test
2.在项目目录中准备用于镜像构建的 Dockerfile 及其相关文件
[root@host1 multi-test]# vi Dockerfile
[root@host1 multi-test]# cat Dockerfile
FROM nginx:1.20
# 修正指令拼写:coPY → COPY(Docker指令需大写)
COPY ./index.html /usr/share/nginx/html/index.html
[root@host1 multi-test]# vi index.html
[root@host1 multi-test]# cat index.html
<h1>欢迎访问Web 站点!</h1>
3.在项目目录中创建一个定义服务的规范配置的基本文件compose.yaml
[root@host1 multi-test]# vi compose.yaml
[root@host1 multi-test]# cat compose.yaml
services:web:image: myweb-app:latest # 修复:镜像名空格改为连字符(避免解析错误)depends_on: # 修复:关键字应为depends_on(下划线连接)- db- cacherestart: always # 可选:增加自动重启提高稳定性db:image: postgres:latestports:- "5432:5432" # 修复:端口需用列表格式(加短横线和引号)environment: # 可选:添加postgres必要环境变量(默认需要密码)POSTGRES_PASSWORD: examplepasswordPOSTGRES_USER: appuserPOSTGRES_DB: appdbvolumes:- postgres_data:/var/lib/postgresql/data # 可选:数据持久化restart: alwayscache:image: redis:latest # 修复:服务名后的分号改为冒号ports:- "6379:6379" # 修复:端口列表格式(加短横线和引号),ports后的分号改为冒号volumes:- redis_data:/data # 可选:数据持久化restart: alwaysvolumes: # 定义数据卷(如果使用了volumes配置)postgres_data:redis_data:
4.创建一个覆盖文件 compose.override.yaml,针对开发环境对该文件进行配置,向主机Web 端口,绑定挂载,定义环境变量,并构建 Web 镜像
[root@host1 multi-test]# vi compose.override.yaml
[root@host1 multi-test]# cat compose.override.yaml
services:web:build: .volumes:- .:/codeports:- "8883:80"environment:DEBUG: 'true'db:image: postgres:latestvolumes:- ./data/db:/var/lib/postgresql/data# 修复环境变量格式:去掉列表项符号(-),直接用冒号分隔键值对environment:POSTGRES_DB: postgresPOSTGRES_USER: postgresPOSTGRES_PASSWORD: postgresports:- "5432:5432"restart: always
5.执行 docker compose up -d 命令运行应用程序,该命令会自动读取覆盖文件,完成了3个服务的启动之后,再执行以下命令列出服务进行验证
[root@host1 multi-test]# docker compose up -d
[+] Running 16/16✔ db Pulled 63.5s ✔ ce1261c6d567 Already exists 0.0s ✔ 88af8c060117 Pull complete 2.9s ✔ 27009aeaf88d Pull complete 4.2s ✔ 4043a0df36b4 Pull complete 4.3s ✔ b6038fb9c5fa Pull complete 11.7s ✔ 98a86eab6353 Pull complete 11.8s ✔ 73dfcde3cab4 Pull complete 11.9s ✔ 4fcee84ce502 Pull complete 11.9s ✔ b669c29718de Pull complete 33.8s ✔ e5baa5776b92 Pull complete 33.8s ✔ b1b94b4bf231 Pull complete 33.8s ✔ cfcb89870710 Pull complete 33.9s ✔ a80dd9fac9bc Pull complete 33.9s ✔ 1d83e33d11e9 Pull complete 33.9s ! web Warning Get "https://registry-1.docker.io/v2/": net/http: r... 40.7s
[+] Building 30.8s (9/9) FINISHED => [internal] load local bake definitions 0.0s=> => reading from stdin 481B 0.0s=> [internal] load build definition from Dockerfile 0.0s=> => transferring dockerfile: 230B 0.0s=> [internal] load metadata for docker.io/library/nginx:1.20 19.1s=> [internal] load .dockerignore 0.0s=> => transferring context: 2B 0.0s=> [internal] load build context 0.0s=> => transferring context: 130B 0.0s=> [1/2] FROM docker.io/library/nginx:1.20@sha256:38f8c1d9613f3f42e7969c3b1dd5c3277e635d4576 10.9s=> => resolve docker.io/library/nginx:1.20@sha256:38f8c1d9613f3f42e7969c3b1dd5c3277e635d45767 0.0s=> => sha256:a76df3b4f1478766631c794de7ff466aca466f995fd5bb216bb9643a3dd2a6bb 1.57kB / 1.57kB 0.0s=> => sha256:214ca5fb90323fe769c63a12af092f2572bf1c6b300263e09883909fc865d2 31.38MB / 31.38MB 4.5s=> => sha256:38f8c1d9613f3f42e7969c3b1dd5c3277e635d4576713e6453c6193e66270a6d 1.86kB / 1.86kB 0.0s=> => sha256:0584b370e957bf9d09e10f424859a02ab0fda255103f75b3f8c7d410a4e96ed5 7.64kB / 7.64kB 0.0s=> => sha256:50836501937ff210a4ee8eedcb17b49b3b7627c5b7104397b2a6198c569d92 25.34MB / 25.34MB 3.0s=> => sha256:d838e0361e8efc1fb3ec2b7aed16ba935ee9b62b6631c304256b0326c048a330 600B / 600B 0.8s=> => sha256:fcc7a415e354b2e1a2fcf80005278d0439a2f87556e683bb98891414339f9bee 893B / 893B 3.2s=> => sha256:dc73b4533047ea21262e7d35b3b2598e3d2c00b6d63426f47698fe2adac5b1d6 664B / 664B 3.9s=> => sha256:e8750203e98541223fb970b2b04058aae5ca11833a93b9f3df26bd835f66d223 1.39kB / 1.39kB 4.2s=> => extracting sha256:214ca5fb90323fe769c63a12af092f2572bf1c6b300263e09883909fc865d260 4.2s=> => extracting sha256:50836501937ff210a4ee8eedcb17b49b3b7627c5b7104397b2a6198c569d9231 1.7s=> => extracting sha256:d838e0361e8efc1fb3ec2b7aed16ba935ee9b62b6631c304256b0326c048a330 0.0s=> => extracting sha256:fcc7a415e354b2e1a2fcf80005278d0439a2f87556e683bb98891414339f9bee 0.0s=> => extracting sha256:dc73b4533047ea21262e7d35b3b2598e3d2c00b6d63426f47698fe2adac5b1d6 0.0s=> => extracting sha256:e8750203e98541223fb970b2b04058aae5ca11833a93b9f3df26bd835f66d223 0.0s=> [2/2] COPY ./index.html /usr/share/nginx/html/index.html 0.5s=> exporting to image 0.0s=> => exporting layers 0.0s=> => writing image sha256:9de860f125eb317b68812b16870528193a439f667aef15c7225afaa1fe12e57d 0.0s=> => naming to docker.io/library/myweb-app:latest 0.0s=> resolving provenance for metadata file 0.0s
[+] Running 6/6✔ myweb-app:latest Built 0.0s ✔ Network multi-test_default Created 0.1s ✔ Volume "multi-test_redis_data" Created 0.0s ✔ Container multi-test-db-1 Started 0.9s ✔ Container multi-test-cache-1 Started 0.9s ✔ Container multi-test-web-1 Started 1.3s
[root@host1 multi-test]# docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
multi-test-cache-1 redis:latest "docker-entrypoint.s…" cache 2 minutes ago Up 2 minutes 0.0.0.0:6379->6379/tcp, [::]:6379->6379/tcp
multi-test-db-1 postgres:latest "docker-entrypoint.s…" db 2 minutes ago Up 2 minutes 0.0.0.0:5432->5432/tcp, [::]:5432->5432/tcp
multi-test-web-1 myweb-app:latest "/docker-entrypoint.…" web 2 minutes ago Up 2 minutes 0.0.0.0:8883->80/tcp, [::]:8883->80/tcp
[root@host1 ~]# curl http://127.0.0.1:8883
<h1>欢迎访问Web 站点!</h1>
6.在生产环境中使用专门的 Compose 文件定义应用程序会更好。针对生产环境创建另一个覆盖文件 compose.prod.yaml
[root@host1 multi-test]# vi compose.prod.yaml
[root@host1 multi-test]# cat compose.prod.yaml
services: # 修正:分号;改为冒号:(YAML根节点必需)web: # 修正:服务名"webs"改为"web"(拼写错误),补充冒号:image: nginx:latest # 补充:Web服务基础镜像(根据实际业务替换)ports: # 修正:分号;改为冒号:- "80:80" # 修正:端口添加引号,符合列表项格式environment:PRODUCTION: 'true' # 修正:分号;改为冒号:(键值对标准格式)db: # 修正:补充服务层级,确保与web同级image: postgres:latest # 补充:PostgreSQL基础镜像(必需)volumes:- postgres:/data/postgres # 卷映射格式正确(卷名:容器路径)environment:POSTGRES_USER: ${POSTGRES_USER:-postgres} # 修正:1.空格→下划线;2.S→$;3.删除多余/;4.默认值法${key:-default}POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-changeme} # 同上,修正变量引用格式PGDATA: /data/postgres # 正确指定PostgreSQL数据目录cache: # 修正:补充服务定义,确保层级正确image: redis:latest # 补充:Redis基础镜像(必需)environment:TTL: '500' # 环境变量键值对格式正确# 若需持久化可添加:# volumes:# - redis_data:/data# 修正:卷定义节点(与services同级)
volumes:postgres: # 声明db服务使用的卷(用于数据持久化)# redis_data: # 若cache需要持久化,取消注释此行
7.使用这个针对生产环境的 Compose 文件进行应用程序部署,可以执行以下命令
[root@host1 multi-test]# docker compose -f compose.yaml -f compose.prod.yaml up -d
[+] Running 5/5✔ Volume "multi-test_postgres" Created 0.0s ✔ Volume "multi-test_postgres_data" Created 0.0s ✔ Container multi-test-db-1 Started 1.4s ✔ Container multi-test-cache-1 Started 1.4s ✔ Container multi-test-web-1 Started 1.4s
[root@host1 multi-test]# curl 127.0.0.1
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p><p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p><p><em>Thank you for using nginx.</em></p>
</body>
</html>
[root@host1 multi-test]# vi compose.prod.yaml
[root@host1 multi-test]# cat compose.prod.yaml
services: # 修正:分号;改为冒号:(YAML根节点必需)web: # 修正:服务名"webs"改为"web"(拼写错误),补充冒号:image: nginx:latest # 补充:Web服务基础镜像(根据实际业务替换)ports: # 修正:分号;改为冒号:- "80:80" # 修正:端口添加引号,符合列表项格式environment:PRODUCTION: 'true' # 修正:分号;改为冒号:(键值对标准格式)db: # 修正:补充服务层级,确保与web同级image: postgres:latest # 补充:PostgreSQL基础镜像(必需)volumes:- postgres:/data/postgres # 卷映射格式正确(卷名:容器路径)- ./index.html:/usr/share/nginx/html/index.htmlrestart: alwaysenvironment:POSTGRES_USER: ${POSTGRES_USER:-postgres} # 修正:1.空格→下划线;2.S→$;3.删除多余/;4.默认值法${key:-default}POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-changeme} # 同上,修正变量引用格式PGDATA: /data/postgres # 正确指定PostgreSQL数据目录cache: # 修正:补充服务定义,确保层级正确image: redis:latest # 补充:Redis基础镜像(必需)environment:TTL: '500' # 环境变量键值对格式正确# 若需持久化可添加:# volumes:# - redis_data:/data# 修正:卷定义节点(与services同级)
volumes:postgres: # 声明db服务使用的卷(用于数据持久化)# redis_data: # 若cache需要持久化,取消注释此行[root@host1 multi-test]# vi compose.prod.yaml
[root@host1 multi-test]# cat compose.prod.yaml
services: # 根节点web: # Nginx 服务(负责网页展示,首页挂载必须放这里!)image: nginx:latestports:- "80:80"environment:PRODUCTION: 'true'# 关键修正:将 index.html 挂载到 web 服务(Nginx 容器),而非 db 服务volumes:- ./index.html:/usr/share/nginx/html/index.htmlrestart: always # 生产环境服务自动重启db: # Postgres 数据库服务(仅需数据卷,无需网页文件)image: postgres:latestvolumes:- postgres:/data/postgres # 仅保留数据库数据卷(正确配置)environment:POSTGRES_USER: ${POSTGRES_USER:-postgres}POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-changeme}PGDATA: /data/postgresrestart: always # 数据库服务自动重启cache: # Redis 缓存服务image: redis:latestenvironment:TTL: '500'restart: always # 缓存服务自动重启# 可选:Redis 持久化(需时取消注释)# volumes:# - redis_data:/data# 卷定义(与 services 同级)
volumes:postgres: # 数据库数据卷# redis_data: # 若启用 Redis 持久化,取消注释
[root@host1 multi-test]# cat index.html
<h1>欢迎访问生产环境Web站点!</h1>
[root@host1 multi-test]# docker compose -f compose.prod.yaml up -d --force-recreate
[+] Running 3/3✔ Container multi-test-web-1 Started 1.6s ✔ Container multi-test-db-1 Started 1.6s ✔ Container multi-test-cache-1 Started 1.4s
[root@host1 multi-test]# curl 127.0.0.1
<h1>欢迎访问生产环境Web站点!</h1>
8.执行 docker compose down --volumes 命令停止并清理服务
[root@host1 multi-test]# docker compose down --volume
WARN[0000] --volume is deprecated, please use --volumes
WARN[0000] --volume is deprecated, please use --volumes
WARN[0000] --volume is deprecated, please use --volumes
WARN[0000] --volume is deprecated, please use --volumes
[+] Running 5/5✔ Container multi-test-web-1 Removed 0.3s ✔ Container multi-test-db-1 Removed 0.2s ✔ Container multi-test-cache-1 Removed 0.3s ✔ Volume multi-test_redis_data Removed 0.0s ✔ Network multi-test_default Removed 0.2s