Docker Compose 入门实战:一条命令跑起“网页 + 接口”
关键词:Docker Compose、多容器编排、静态网站、后端接口
上一篇我们用 Docker 把单个静态网页装进了容器,一个容器跑一个服务,够用了。但真实项目很少只有一个服务:网页后面往往还要一个接口服务,两个容器要一起启动、还要能互相访问——一个一个 docker run 很容易手忙脚乱。这时候就该用 Docker Compose:把多个容器的配置写进一个文件,一条命令全部跑起来。
本文以前文的静态页面为例,再加一个极简的接口服务做搭配,假设服务器上已经装好 Docker 和 Docker Compose。
一、Compose 是什么
可以把它理解成"容器的启动清单":以前写在 docker run 参数里的东西——用什么镜像、映射哪个端口、容器叫什么——现在都写进 docker-compose.yml,以后启动、停止、重建都按这份清单来,不用再背一长串命令。
先确认 Compose 能用:
docker compose version
能输出版本号就说明没问题(新版 Compose 是 docker compose,中间有个空格;老版 docker-compose 是独立命令,效果一样)。
二、准备两个服务
目录结构很简单,两个文件夹各放一个服务:
my-app/
├── docker-compose.yml
├── web/
│ ├── Dockerfile
│ └── index.html
└── api/
├── Dockerfile
└── app.py
网页服务沿用上一篇的做法:
# web/Dockerfile
FROM nginx:alpine
COPY index.html /usr/share/nginx/html/index.html
EXPOSE 80
接口服务用一个极简的 Python 服务做示例,只返回一句话,重点是看两个容器怎么配合,而不是接口本身写得多复杂:
# api/app.py
from http.server import BaseHTTPRequestHandler, HTTPServer
class Handler(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header("Content-Type", "application/json")
self.end_headers()
self.wfile.write(b'{"message": "hello from api"}')
def log_message(self, *args):
pass
HTTPServer(("0.0.0.0", 8000), Handler).serve_forever()
# api/Dockerfile
FROM python:3.12-alpine
WORKDIR /app
COPY app.py .
EXPOSE 8000
CMD ["python", "app.py"]
三、写 docker-compose.yml
这是核心文件,两个服务一次写清:
services:
web:
build: ./web
ports:
- "80:80"
api:
build: ./api
ports:
- "8000:8000"
逐行看:
services下面每个名字就是一个服务,web和api只是名字,起什么都行build: ./web表示用这个目录下的 Dockerfile 现场构建镜像,不用先手动docker buildports: "80:80"和上一篇-p 80:80是一回事,左边是主机端口,右边是容器端口
四、一条命令跑起来
在 docker-compose.yml 所在的目录执行:
docker compose up -d
up是按清单启动所有服务-d还是后台运行的意思
跑起来后验证两处:浏览器访问服务器公网 IP 能看到网页;访问 http://服务器公网IP:8000 能看到接口返回的 hello from api,就说明两个容器都正常了。
五、日常管理就四个命令
| 命令 | 作用 |
|---|---|
docker compose up -d |
启动(或重建后启动)所有服务 |
docker compose ps |
查看这组服务的状态 |
docker compose logs -f web |
跟踪看某一个服务的日志 |
docker compose down |
停掉并删掉这组容器 |
改了代码怎么办?和上一篇单容器一样,重新构建再启动:
docker compose up -d --build
--build 会先重新构建镜像再启动,不用先手动停、手动删,Compose 会帮你替换掉旧容器。
六、两个新手最容易踩的坑
1. 端口冲突
如果 up 报错说端口已被占用,先想想主机上是不是已经跑着原生 Nginx 或上一篇的单容器。解决办法二选一:停掉冲突的服务,或者把 docker-compose.yml 里的主机端口改成别的,比如 "8080:80"。
2. 服务之间怎么互相访问
在 Compose 的网络里,服务之间用服务名当主机名就能互相访问:网页服务里访问 http://api:8000 就能找到接口服务,不用写 IP,也不用记容器每次变化的地址。这是 Compose 比手动 docker run 省事的关键一点。
结语
单容器是"把一个服务装箱",Compose 是"把一整套服务写成清单"。从 Nginx 到 Docker 再到 Compose,这三步走完,本地和服务器上跑同一套服务的姿势就基本统一了:开发时一份清单,部署时同一条命令。下一篇可以继续往下走:给这套服务加上数据卷,让数据在容器重建后也不丢。
- 点赞
- 收藏
- 关注作者
评论(0)