Docker 实战:给前端开发者的一份指南
两年前我第一次接触 Docker,完全是一脸懵。镜像、容器、仓库……这些词听着就很运维。
后来被迫用了一段时间,发现确实好用。现在我的所有项目都 Docker 化了,开发环境再也没出过问题。
Docker 是什么
一句话:Docker 让应用在任何机器上都能以相同的方式运行。
传统部署:
开发环境能跑 → 测试环境报错 → 生产环境炸了
Docker 部署:
哪里都能跑
原理是把应用和它的运行环境(操作系统、依赖库、配置)打包成一个”镜像”,然后在这台机器上跑这个镜像。
核心概念
镜像(Image)
只读模板,包含应用和运行环境。类似虚拟机快照,但更轻量。
容器(Container)
镜像的运行实例。一个镜像可以启动多个容器,互不干扰。
Dockerfile
构建镜像的脚本,告诉 Docker 怎么打包你的应用。
仓库(Registry)
存放镜像的地方。Docker Hub 是官方仓库,国内可以用阿里云、腾讯云的镜像服务。
从零开始:容器化一个 Node.js 应用
假设有一个简单的 Express 应用:
// app.js
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.send('Hello Docker!');
});
app.listen(3000);
第一步:写 Dockerfile
# 基础镜像
FROM node:20-alpine
# 工作目录
WORKDIR /app
# 复制 package.json(利用缓存)
COPY package*.json ./
# 安装依赖
RUN npm install --production
# 复制代码
COPY . .
# 暴露端口
EXPOSE 3000
# 启动命令
CMD ["node", "app.js"]
几个要点:
alpine版本体积小,适合生产环境WORKDIR创建并进入工作目录- 先复制
package.json,利用 Docker 缓存层,依赖不变就不用重装 CMD是容器启动时执行的命令
第二步:构建镜像
docker build -t my-app:1.0 .
-t 给镜像打标签,格式是 name:tag。
第三步:运行容器
docker run -d -p 3000:3000 my-app:1.0
-d:后台运行-p 3000:3000:端口映射,主机端口:容器端口
访问 http://localhost:3000 就能看到结果。
进阶:多阶段构建
上面的 Dockerfile 有个问题:镜像里包含了 node_modules,体积很大。
多阶段构建可以解决这个问题:
# 阶段1:构建
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# 阶段2:运行
FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
EXPOSE 3000
CMD ["node", "dist/index.js"]
最终镜像只包含构建产物,不包含源码和构建工具,体积小很多。
Docker Compose:多容器编排
实际项目往往不止一个容器。比如一个典型的 Web 应用:
- Node.js 应用
- MySQL 数据库
- Redis 缓存
- Nginx 反向代理
Docker Compose 可以一键启动所有容器:
# docker-compose.yml
version: '3.8'
services:
app:
build: .
ports:
- "3000:3000"
environment:
- DB_HOST=db
- REDIS_HOST=redis
depends_on:
- db
- redis
db:
image: mysql:8
environment:
- MYSQL_ROOT_PASSWORD=secret
- MYSQL_DATABASE=myapp
volumes:
- db_data:/var/lib/mysql
redis:
image: redis:7-alpine
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
- app
volumes:
db_data:
启动:
docker-compose up -d
停止:
docker-compose down
常用命令速查
# 查看运行中的容器
docker ps
# 查看所有容器(包括停止的)
docker ps -a
# 查看镜像列表
docker images
# 进入容器
docker exec -it <container_id> sh
# 查看容器日志
docker logs -f <container_id>
# 停止容器
docker stop <container_id>
# 删除容器
docker rm <container_id>
# 删除镜像
docker rmi <image_id>
# 清理无用资源
docker system prune
实战经验
1. 不要用 latest 标签
latest 会指向最新版本,每次拉取可能不一样。生产环境要用具体版本:
FROM node:20.11.0-alpine # 好
FROM node:latest # 坏
2. 利用 .dockerignore
类似 .gitignore,排除不需要的文件:
node_modules
.git
.env
*.log
3. 健康检查
HEALTHCHECK --interval=30s CMD curl -f http://localhost:3000/health || exit 1
Docker 会定期检查,如果失败就自动重启容器。
4. 日志处理
容器日志默认存到 /var/lib/docker/containers/,长期运行会占满磁盘。
推荐用日志驱动输出到文件或日志服务:
docker run --log-driver json-file --log-opt max-size=10m --log-opt max-file=3 my-app
国内镜像加速
Docker Hub 在国内访问较慢,可以配置镜像加速:
// /etc/docker/daemon.json
{
"registry-mirrors": [
"https://docker.mirrors.ustc.edu.cn",
"https://hub-mirror.c.163.com"
]
}
重启 Docker 生效:
sudo systemctl restart docker
总结
Docker 的学习曲线有点陡,但投入是值得的。一旦习惯了这个工作方式,你会发现:
- 新同事入职,
docker-compose up一条命令就能跑起来 - 换电脑不需要重新配置环境
- 部署到任何服务器都是一样的流程
建议从小项目开始尝试,遇到问题再查文档。实践是最好的老师。