后端工程Technical Deep Dive
Docker 基础与实战:从小白到生产
发布时间2026/03/29
分类后端工程
预计阅读10 分钟
作者吴长龙
*
Docker 基础与实战:从小白到生产
01.内容
# Docker 基础与实战:从小白到生产
Docker 是现代应用部署的事实标准。本文从基础概念到 Dockerfile 最佳实践,系统介绍 Docker 的核心知识和生产环境应用。
02.一、核心概念
1.1 什么是 Docker
bash snippetbash
# Docker vs 虚拟机
# 虚拟机:完整操作系统 + 虚拟硬件 → 体积大(GB级),启动慢(分钟级)
# Docker:共享宿主机内核 → 体积小(MB级),启动快(秒级)
# 核心概念
# 镜像(Image):只读模板,用于创建容器
# 容器(Container):镜像的运行实例
# 仓库(Repository):存储镜像的地方1.2 基础命令
bash snippetbash
# 镜像操作
docker pull node:20-alpine # 拉取镜像
docker images # 列出镜像
docker rmi node:20-alpine # 删除镜像
docker build -t my-app:1.0 . # 构建镜像
docker tag my-app:1.0 my-registry.com/my-app:1.0 # 打标签
# 容器操作
docker run -d -p 3000:3000 --name my-app my-app # 运行容器
docker ps # 列出运行中容器
docker ps -a # 所有容器
docker logs -f my-app # 查看日志
docker exec -it my-app sh # 进入容器
docker stop my-app # 停止容器
docker rm my-app # 删除容器
docker rm -f my-app # 强制删除
# 进阶
docker inspect my-app # 查看容器详情
docker stats my-app # 资源使用
docker cp my-app:/app/logs ./logs # 复制文件03.二、Dockerfile 最佳实践
2.1 基础 Dockerfile
dockerfile snippetdockerfile
# ❌ 糟糕的 Dockerfile
FROM ubuntu:20.04
RUN apt-get update
RUN apt-get install -y nodejs npm
COPY . /app
RUN cd /app && npm install
EXPOSE 3000
CMD ["node", "/app/index.js"]dockerfile snippetdockerfile
# ✅ 优化的 Dockerfile
# 1. 使用特定版本标签
FROM node:20-alpine
# 2. 设置工作目录
WORKDIR /app
# 3. 先复制依赖文件,利用缓存
COPY package*.json ./
RUN npm ci --only=production
# 4. 再复制源码
COPY . .
# 5. 非 root 用户运行(安全)
RUN addgroup -g 1001 -S nodejs && \
adduser -S nodejs -u 1001
USER nodejs
# 6. 暴露端口
EXPOSE 3000
# 7. 启动命令
CMD ["node", "index.js"]2.2 多阶段构建
dockerfile snippetdockerfile
# 构建 Node.js 应用
# 阶段1:构建
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# 阶段2:运行
FROM node:20-alpine AS production
WORKDIR /app
# 复制构建产物
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY package*.json ./
# 生产依赖
RUN npm ci --only=production
USER nodejs
EXPOSE 3000
CMD ["node", "dist/index.js"]2.3 前端构建
dockerfile snippetdockerfile
# React/Vue 构建
FROM node:20-alpine AS builder
WORKDIR /app
# 安装依赖(利用缓存)
COPY package*.json ./
RUN npm ci
# 构建
COPY . .
ENV NODE_ENV=production
RUN npm run build
# 生产服务
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]nginx snippetnginx
# nginx.conf
server {
listen 80;
root /usr/share/nginx/html;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
# 缓存静态资源
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
}04.三、Docker 网络与存储
3.1 网络
bash snippetbash
# 创建网络
docker network create my-network
# 运行容器并加入网络
docker run -d --name api --network my-network my-api
docker run -d --name web --network my-web-network my-web
# 容器间通信(使用服务名)
# 在 api 容器中访问 web:
# curl http://web:8080
# 在 web 容器中访问 api:
# curl http://api:3000yaml snippetyaml
# docker-compose.yml 中的网络
services:
api:
build: ./api
networks:
- backend
web:
build: ./web
depends_on:
- api
networks:
- frontend
- backend
networks:
frontend:
driver: bridge
backend:
driver: bridge3.2 存储
bash snippetbash
# 匿名卷(容器删除后丢失)
docker run -v /app/data my-app
# 命名卷(持久化)
docker volume create my-data
docker run -v my-data:/app/data my-app
# 绑定挂载(开发用,修改即时生效)
docker run -v $(pwd):/app -w /app node:20 npm run devyaml snippetyaml
# docker-compose.yml 中的存储
services:
db:
image: postgres:15
volumes:
# 命名卷
- postgres-data:/var/lib/postgresql/data
# 绑定挂载(初始化脚本)
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
volumes:
postgres-data:05.四、生产环境配置
4.1 Node.js 生产配置
dockerfile snippetdockerfile
# node:production.Dockerfile
FROM node:20-alpine
# 环境变量
ENV NODE_ENV=production \
PORT=3000
WORKDIR /app
# 安全:非 root 用户
RUN addgroup -g 1001 -S nodejs && \
adduser -S nodejs -u 1001
# 复制依赖
COPY package*.json ./
RUN npm ci --only=production && \
npm cache clean --force
# 复制源码
COPY --chown=nodejs:nodejs . .
USER nodejs
EXPOSE $PORT
# 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD node -e "require('http').get('http://localhost:$PORT/health', (r) => process.exit(r.statusCode === 200 ? 0 : 1))"
CMD ["node", "server.js"]4.2 环境变量管理
bash snippetbash
# .env 文件(不提交到 Git)
# .env
DB_HOST=localhost
DB_PORT=5432
API_KEY=your-secret-key
# docker-compose.yml
services:
api:
env_file:
- .env
environment:
- NODE_ENV=production
- LOG_LEVEL=info4.3 日志管理
bash snippetbash
# 限制日志大小
docker run --log-opt max-size=10m --log-opt max-file=3 my-app
# 使用 docker-compose
services:
api:
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"06.五、私有镜像仓库
5.1 Docker Hub
bash snippetbash
# 登录
docker login -u username
# 推送
docker build -t username/my-app:1.0 .
docker push username/my-app:1.0
# 拉取
docker pull username/my-app:1.05.2 GitHub Container Registry
bash snippetbash
# 登录
echo $GITHUB_TOKEN | docker login ghcr.io -u $GITHUB_ACTOR --password-stdin
# 推送
docker build -t ghcr.io/username/my-app:1.0 .
docker push ghcr.io/username/my-app:1.0
# 拉取
docker pull ghcr.io/username/my-app:1.007.六、最佳实践清单
- •[ ] 使用特定版本标签(不用 latest)
- •[ ] 利用层缓存优化构建顺序
- •[ ] 使用 .dockerignore 排除不必要的文件
- •[ ] 以非 root 用户运行容器
- •[ ] 添加健康检查
- •[ ] 合理设置资源限制(CPU、内存)
- •[ ] 使用多阶段构建减小镜像体积
- •[ ] 敏感信息使用环境变量或密钥管理
---
*下一篇文章将介绍 Docker Compose 多容器编排。*