:Docker Compose,用一个 YAML 启动前端、后端和 MongoDB)
Docker 学习笔记五Docker Compose用一个 YAML 启动前端、后端和 MongoDB前面我们已经可以用docker run启动单个容器。但真实项目通常不是一个容器。比如一个全栈项目至少有前端 web 后端 api 数据库 mongo如果全部用docker run命令会变成这样dockernetwork create app-netdockervolume create mongo-datadockerrun-d--namemongo--networkapp-net\-eMONGO_INITDB_ROOT_USERNAMEroot\-eMONGO_INITDB_ROOT_PASSWORD123456\-vmongo-data:/data/db\mongo:7dockerrun-d--nameapi--networkapp-net\-p3000:3000\-eMONGO_URLmongodb://root:123456mongo:27017/app?authSourceadmin\my-api:1.0dockerrun-d--nameweb--networkapp-net\-p8080:80\my-web:1.0能用但不适合长期维护。Docker Compose 就是为了解决这个问题。1. Compose 解决什么问题Compose 的核心价值是用一个 YAML 文件描述多个服务、网络、数据卷和环境变量然后一条命令启动它们。也就是把一堆命令变成dockercompose up-d停止dockercompose down这对前后端 数据库项目非常有用。2. 最小 docker-compose.ymlservices:nginx:image:nginx:alpineports:-8080:80启动dockercompose up-d查看dockercomposeps停止dockercompose down3. services定义服务Compose 文件里的核心是services。services:web:image:nginx:alpine这里的web是服务名。服务名非常重要因为同一个 Compose 网络里服务可以通过服务名互相访问。比如后端访问 MongoDBmongodb://mongo:27017/app这里的mongo就是 Compose 服务名。4. 前端 后端 MongoDB 示例假设目录my-fullstack-app/ web/ Dockerfile api/ Dockerfile docker-compose.ymldocker-compose.ymlservices:mongo:image:mongo:7container_name:app-mongorestart:unless-stoppedenvironment:MONGO_INITDB_ROOT_USERNAME:rootMONGO_INITDB_ROOT_PASSWORD:123456volumes:-mongo-data:/data/dbnetworks:-app-netapi:build:context:./apidockerfile:Dockerfilecontainer_name:app-apirestart:unless-stoppedports:-3000:3000environment:NODE_ENV:productionPORT:3000MONGO_URL:mongodb://root:123456mongo:27017/app?authSourceadmindepends_on:-mongonetworks:-app-netweb:build:context:./webdockerfile:Dockerfilecontainer_name:app-webrestart:unless-stoppedports:-8080:80depends_on:-apinetworks:-app-netvolumes:mongo-data:networks:app-net:driver:bridge启动dockercompose up-d--build这条命令会构建api镜像构建web镜像拉取mongo:7创建mongo-data数据卷创建app-net网络启动三个服务。5. image 和 build 的区别Compose 里常见两种写法5.1 使用已有镜像mongo:image:mongo:7表示直接使用远程或本地已有镜像。5.2 根据 Dockerfile 构建镜像api:build:context:./apidockerfile:Dockerfile表示进入./api目录根据 Dockerfile 构建镜像。简单说字段作用image直接使用已有镜像build根据 Dockerfile 构建镜像6. environment配置环境变量Compose 里可以这样写environment:NODE_ENV:productionPORT:3000也可以用列表environment:-NODE_ENVproduction-PORT3000如果涉及密码不建议直接提交到 GitHub。可以使用.envMONGO_ROOT_USERNAMEroot MONGO_ROOT_PASSWORD123456然后 Composeenvironment:MONGO_INITDB_ROOT_USERNAME:${MONGO_ROOT_USERNAME}MONGO_INITDB_ROOT_PASSWORD:${MONGO_ROOT_PASSWORD}注意.env不要提交到公开仓库。7. volumes数据持久化volumes:-mongo-data:/data/db表示把 Docker 管理的mongo-data数据卷挂载到 MongoDB 容器的/data/db。底部还要声明volumes:mongo-data:这样即使容器删除数据库数据也不会跟着丢。8. networks服务互通networks:app-net:driver:bridge服务加入网络networks:-app-net同一个网络里的服务可以通过服务名访问。api - mongo:27017 web - api:3000不过浏览器访问前端时还是走宿主机映射端口http://localhost:80809. 指定 Compose 子网如果想给 Compose 网络指定子网可以这样写networks:app-net:driver:bridgeipam:config:-subnet:172.30.0.0/16gateway:172.30.0.1完整示例services:mongo:image:mongo:7networks:-app-netnetworks:app-net:driver:bridgeipam:config:-subnet:172.30.0.0/16gateway:172.30.0.1一般学习阶段不需要手动指定除非遇到网络冲突。10. depends_on控制启动顺序depends_on:-mongo表示api服务会在mongo服务之后启动。但要注意depends_on 不等于等待数据库完全准备好。它只是控制容器启动顺序不保证 MongoDB 已经可以接受连接。生产项目里后端最好自己有重试连接机制或者使用 healthcheck。11. 常用 Compose 命令# 启动全部服务dockercompose up-d# 启动并重新构建dockercompose up-d--build# 查看服务状态dockercomposeps# 查看日志dockercompose logs# 持续查看某个服务日志dockercompose logs-fapi# 停止并删除容器、网络dockercompose down# 停止并删除容器、网络、数据卷dockercompose down-v# 进入某个服务容器dockercomposeexecapish# 只重启 apidockercompose restart api12. 第五篇小结Compose 的核心可以这样记services有哪些容器 build/image镜像从哪里来 ports宿主机怎么访问容器 environment容器运行需要哪些配置 volumes哪些数据要持久化 networks容器之间怎么通信如果docker run是手动挡那么 Docker Compose 就是自动挡。单容器学习时用docker run很好多容器项目一定要尽快切到 Compose。下一篇讲最后一步如何把自己构建好的镜像推送到 Docker Hub 或公司镜像仓库。参考资料Docker Compose: https://docs.docker.com/compose/Compose file reference: https://docs.docker.com/reference/compose-file/Compose networking: https://docs.docker.com/compose/how-tos/networking/Compose volumes: https://docs.docker.com/reference/compose-file/volumes/