Docker 与 Compose 上手:把应用装进盒子里
Docker 的价值对个人站点来说不是「微服务」,而是环境可复现:换台机器、重装系统,docker compose up -d 就能回到原来的状态。
一、安装
# 官方脚本(Debian/Ubuntu)
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER # 免 sudo,需重新登录生效
docker version
docker run --rm hello-world国内机器拉镜像慢,配镜像加速:
{
"registry-mirrors": ["https://docker.m.daocloud.io"]
}写入 /etc/docker/daemon.json 后 sudo systemctl restart docker。
二、最高频的命令
docker ps -a # 看容器(不加 -a 只看运行中的)
docker logs -f --tail 100 web # 实时看日志
docker exec -it web sh # 进容器
docker stats # 实时资源占用
docker images
docker rmi $(docker images -f "dangling=true" -q) # 清理悬空镜像
docker system prune -a # 大扫除(会删未使用的镜像,谨慎)三、Dockerfile 的几个要点
# 多阶段构建:构建产物只带走需要的东西,镜像能小一个数量级
FROM node:20-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/html
EXPOSE 80容易踩的点:
- 不要用 root 跑(生产环境):
USER node; .dockerignore必须有,否则node_modules、.git全进镜像;COPY package*.json ./单独一行,能利用缓存层,改代码不重装依赖;- 基础镜像优先
-alpine,体积小很多。
四、一份能直接改的 compose 文件
services:
web:
image: nginx:alpine
container_name: web
restart: unless-stopped
ports:
- "8080:80"
volumes:
- ./html:/usr/share/nginx/html:ro
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
networks:
- app
app:
build: ./app
restart: unless-stopped
environment:
- NODE_ENV=production
- DB_HOST=db
depends_on:
- db
networks:
- app
db:
image: postgres:16-alpine
restart: unless-stopped
environment:
- POSTGRES_PASSWORD=change_me_please
volumes:
- pgdata:/var/lib/postgresql/data
networks:
- app
volumes:
pgdata:
networks:
app:docker compose up -d # 后台启动
docker compose ps
docker compose logs -f app
docker compose down # 停止并移除容器(数据卷保留)
docker compose pull && docker compose up -d # 更新镜像容器之间用服务名互相访问,比如 app 连数据库写
db:5432,不要写 127.0.0.1——容器内的 localhost 是它自己。
五、数据持久化:volume 是重点
容器删了数据就没了,所以数据库一定要挂 volume:
docker volume ls
docker volume inspect pgdata
# 备份:起个临时容器把卷打包
docker run --rm -v pgdata:/data -v $(pwd):/backup alpine \
tar czf /backup/pgdata-$(date +%F).tar.gz -C /data .六、小内存机器上限制资源
1G 内存的小鸡跑多个容器很容易 OOM,加上限制:
services:
app:
image: myapp
mem_limit: 256m
cpus: 0.5
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"最后一条很重要:不限制日志大小,一个跑飞的容器能把磁盘写满。
七、什么时候不用 Docker
说句实话:只跑一个静态站就没必要上 Docker。直接 Nginx 托管,少一层就少一层要维护的东西。
值得用的场景:
- 需要数据库、缓存、后端多个组件协同;
- 想在一台机器上跑多个互不干扰的应用;
- 应用依赖特定运行环境(老版本 Python/Node);
- 需要频繁换机器、要求环境可复现。
