Docker Compose多容器编排入门

单机跑Docker时,docker run敲多了就想吐。尤其是微服务场景,一个Web应用要配MySQL、Redis、Nginx,每次启动都要写一长串参数,端口映射、网络连接、环境变量,漏一个就得排查半天。Docker Compose就是干这个的:用一个YAML文件定义多个容器,一条命令全部拉起来。 先装Compose Docker Desktop自带Compose。Linux服务器需要单独装,官方推荐用插件方式:
sudo apt update
sudo apt install docker-compose-plugin
装完验证:
docker compose version
注意是`docker compose`,中间没横杠。老版本用`docker-compose`,新版的插件模式更推荐。 写第一个compose文件 项目目录结构:
myapp/
  docker-compose.yml
  web/
    app.py
    Dockerfile
  db/
    init.sql
核心就是docker-compose.yml:
version: '3.8'

services:
  web:
    build: ./web
    ports:
      - "5000:5000"
    depends_on:
      - db
    environment:
      - DB_HOST=db
      - DB_USER=root
      - DB_PASS=secret

  db:
    image: mysql:8.0
    volumes:
      - db_data:/var/lib/mysql
      - ./db/init.sql:/docker-entrypoint-initdb.d/init.sql
    environment:
      - MYSQL_ROOT_PASSWORD=secret
      - MYSQL_DATABASE=myapp

volumes:
  db_data:
解释几个关键点: services:每个顶级key就是一个容器,Compose会为每个service创建一个容器实例。service name同时作为DNS主机名,所以web里可以直接用`db`连接数据库,不用写IP。 depends_on:控制启动顺序。这里web依赖db,Compose会先启动db再启动web。但注意depends_on只保证启动顺序,不保证db服务已经就绪。MySQL启动需要时间,web启动时可能连不上。解决办法是在应用代码里加重试,或者用wait-for-it脚本。 volumes:两种写法。`db_data:/var/lib/mysql`是命名卷,数据持久化在Docker管理的目录里。`./db/init.sql:/docker-entrypoint-initdb.d/init.sql`是绑定挂载,把本地文件映射到容器里,MySQL镜像会自动执行init.sql初始化数据库。 启动和停止 在docker-compose.yml所在目录执行:
docker compose up -d
-d是后台运行。不加-d会前台输出日志,Ctrl+C停止所有容器。 查看状态:
docker compose ps
看日志:
docker compose logs -f web
-f持续跟踪,类似tail -f。可以指定service名,不指定则输出所有。 停止并删除容器、网络、卷:
docker compose down -v
-v会删除命名卷,慎用。如果只是想停掉容器,保留数据,用`docker compose stop`,下次`docker compose start`恢复。 多环境配置 开发和生产环境通常有差异。Compose支持多个文件覆盖:
# docker-compose.yml 公共配置
# docker-compose.override.yml 开发环境覆盖(自动加载)
# docker-compose.prod.yml 生产环境
启动生产环境:
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
后面的文件覆盖前面的。比如公共配置里暴露端口3000,生产文件里改成80。 网络细节 Compose自动创建一个默认网络,所有service都加入这个网络,通过service name互相访问。如果想手动控制:
services:
  web:
    networks:
      - frontend
      - backend
  api:
    networks:
      - backend
  db:
    networks:
      - backend

networks:
  frontend:
  backend:
这样web同时接入两个网络,api和db只在backend网络里,无法被外部直接访问。数据库不暴露端口,只有api能连,安全一些。 实际踩坑记录 – 容器内连接localhost是容器自己,不是宿主机。要连宿主机服务用`host.docker.internal`(Windows/Mac)或`–network=host`(Linux)。 – 环境变量写在yml里,别写在Dockerfile里。Dockerfile里的ENV是构建时,Compose的environment是运行时,后者可以覆盖前者。 – 数据卷权限问题:MySQL容器用uid 999运行,宿主机挂载的目录权限不对会导致启动失败。加`:z`或设置目录权限为999:999。 – 生产环境别用`build`,用`image`指定已经push到仓库的镜像。在云服务器上部署时,我们团队用雨云,直接拉镜像跑Compose,稳定性不错,性价比也高。 一个完整的web+redis+nginx示例
version: '3.8'

services:
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
    depends_on:
      - web

  web:
    build: .
    expose:
      - "8000"
    environment:
      - REDIS_HOST=redis
    depends_on:
      - redis

  redis:
    image: redis:7-alpine
    volumes:
      - redis_data:/data

volumes:
  redis_data:
nginx反向代理到web的8000端口,web用redis做缓存。expose只暴露给内部网络,不映射宿主机端口,安全。 写Compose的核心就两点:搞清楚service之间的依赖和通信方式,管理好数据和配置的持久化。剩下的就是根据业务需求堆service,每个容器只做一件事,互相配合。

雨云是国内一家老牌云服务商,提供高性价比的云服务器和虚拟主机。我用它部署了好几个项目,速度和稳定性都不错。通过 https://www.rainyun.com/SAJA_ 注册可以领一张 5折优惠券,有需要的朋友可以看看。

© 版权声明
THE END
喜欢就支持一下吧
点赞7 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容