|
|
今天我们要完成一个重要任务:从零开始编写Dockerfile,将一个真实的Node.js应用打包成Docker镜像。
你将学会:
✅ 理解Dockerfile的核心语法和最佳实践
✅ 掌握FROM、RUN、COPY、CMD等关键指令
✅ 独立完成Node.js应用的容器化
✅ 优化镜像大小和构建速度
难度等级:⭐⭐⭐☆☆(进阶实践)
所需时间:约 30-40 分钟
前置要求:
已安装Docker(参考Day 2)
了解基本的Linux命令
具备Node.js基础知识(可选)
准备好了吗?让我们开始构建自己的第一个Docker镜像!
━━━━━━━━━━━━━━━━━━━━
🛠️ 环境准备
在开始之前,请确保你的环境满足以下要求:
系统要求
| 项目 | 要求 | 检查方法 |
|------|------|----------|
| 操作系统 | macOS 10.15+ / Windows 10+ / Linux | - |
| Docker版本 | 20.10+ ||
| 内存 | 至少 4GB | - |
| 磁盘空间 | 至少 2GB | - |
检查命令
- # 检查Docker是否安装
- docker --version
- # 检查Docker是否运行
- docker ps
- # 查看Docker系统信息
- docker info
复制代码
如果以上命令报错,请先阅读 [Day 2 - Docker安装指南]。
准备工作目录
- # 创建项目目录
- mkdir -p ~/docker-practice/day08-nodejs-app
- cd ~/docker-practice/day08-nodejs-app
- # 创建应用目录结构
- mkdir -p src public
复制代码
✅ 环境准备完成,开始正式操作!
━━━━━━━━━━━━━━━━━━━━
📖 操作步骤
步骤1:创建Node.js示例应用
目标:准备一个简单但完整的Web应用用于容器化
创建package.json:- cat > package.json << 'EOF'
- {
- "name": "docker-nodejs-demo",
- "version": "1.0.0",
- "description": "Docker Node.js示例应用",
- "main": "src/server.js",
- "scripts": {
- "start": "node src/server.js",
- "dev": "nodemon src/server.js"
- },
- "dependencies": {
- "express": "^4.18.2"
- },
- "devDependencies": {
- "nodemon": "^3.0.1"
- }
- }
- EOF
复制代码
创建应用主文件:- cat > src/server.js << 'EOF'
- const express = require('express');
- const app = express();
- const PORT = process.env.PORT || 3000;
- // 静态文件服务
- app.use(express.static('public'));
- // API路由
- app.get('/api/health', (req, res) => {
- res.json({
- status: 'healthy',
- timestamp: new Date().toISOString(),
- environment: process.env.NODE_ENV || 'development'
- });
- });
- app.get('/api/info', (req, res) => {
- res.json({
- app: 'Docker Node.js Demo',
- version: '1.0.0',
- node: process.version,
- platform: process.platform
- });
- });
- // 启动服务器
- app.listen(PORT, '0.0.0.0', () => {
- console.log(`🚀 Server running on http://0.0.0.0:${PORT}`);
- console.log(`📝 Environment: ${process.env.NODE_ENV || 'development'}`);
- });
- EOF
复制代码
创建前端页面:- cat > public/index.html << 'EOF'
- <!DOCTYPE html>
- <html lang="zh-CN">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Docker Node.js Demo</title>
- <style>
- body {
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Arial, sans-serif;
- max-width: 800px;
- margin: 50px auto;
- padding: 20px;
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
- color: white;
- }
- .container {
- background: rgba(255,255,255,0.1);
- padding: 30px;
- border-radius: 10px;
- backdrop-filter: blur(10px);
- }
- h1 { margin-top: 0; }
- button {
- background: #4CAF50;
- color: white;
- border: none;
- padding: 10px 20px;
- margin: 5px;
- cursor: pointer;
- border-radius: 5px;
- font-size: 16px;
- }
- button:hover { background: #45a049; }
- #result {
- margin-top: 20px;
- padding: 15px;
- background: rgba(0,0,0,0.2);
- border-radius: 5px;
- font-family: monospace;
- }
- </style>
- </head>
- <body>
- <div class="container">
- <h1>🐳 Docker + Node.js 演示应用</h1>
- <p>这是一个运行在Docker容器中的Node.js应用</p>
- <div>
- <button onclick="checkHealth()">健康检查</button>
- <button onclick="getInfo()">获取信息</button>
- </div>
- <div id="result"></div>
- </div>
- <script>
- async function checkHealth() {
- const res = await fetch('/api/health');
- const data = await res.json();
- document.getElementById('result').innerHTML =
- `<strong>健康状态:</strong><br>${JSON.stringify(data, null, 2)}`;
- }
- async function getInfo() {
- const res = await fetch('/api/info');
- const data = await res.json();
- document.getElementById('result').innerHTML =
- `<strong>应用信息:</strong><br>${JSON.stringify(data, null, 2)}`;
- }
- </script>
- </body>
- </html>
- EOF
复制代码
验证应用结构:
预期输出:- .
- ├── package.json
- ├── public
- │ └── index.html
- └── src
- └── server.js
复制代码
✅ 检查点:确认所有文件已创建完成
━━━━━━━━━━━━━━━━━━━━
步骤2:编写基础Dockerfile
目标:创建第一个Dockerfile,理解核心指令
创建Dockerfile:- cat > Dockerfile << 'EOF'
- # 第1步:选择基础镜像
- FROM node:18-alpine
- # 第2步:设置工作目录
- WORKDIR /app
- # 第3步:复制package.json
- COPY package*.json ./
- # 第4步:安装依赖
- RUN npm install --production
- # 第5步:复制应用代码
- COPY . .
- # 第6步:暴露端口
- EXPOSE 3000
- # 第7步:定义启动命令
- CMD ["npm", "start"]
- EOF
复制代码
Dockerfile指令详解:
| 指令 | 作用 | 示例 |
|------|------|------|
|| 指定基础镜像 ||
|| 设置工作目录 ||
|| 复制文件到镜像 ||
|| 执行命令(构建时) ||
|| 声明端口 ||
|| 容器启动命令 ||
关键概念解释:
FROM node:18-alpine
:使用Node.js 18版本
:基于Alpine Linux(体积小,约5MB)
为什么选alpine?体积小,安全性高,启动快
WORKDIR /app
在容器内创建/app目录
后续所有操作都在此目录进行
相当于- RUN mkdir /app && cd /app
复制代码
分层复制的技巧- COPY package*.json ./ # 先复制依赖文件
- RUN npm install # 安装依赖
- COPY . . # 再复制代码
复制代码 利用Docker缓存机制
代码变更时不会重新安装依赖
CMD vs RUN
:构建镜像时执行(如安装软件)
:容器启动时执行(如启动应用)
✅ 检查点:Dockerfile已创建,理解每行指令的作用
━━━━━━━━━━━━━━━━━━━━
步骤3:构建Docker镜像
目标:将应用打包成Docker镜像
构建命令:- # 基础构建命令
- docker build -t my-nodejs-app:1.0 .
- # 参数说明:
- # -t: 指定镜像名称和标签
- # my-nodejs-app: 镜像名称
- # 1.0: 版本标签
- # .: 构建上下文(当前目录)
复制代码
构建过程输出:- [+] Building 45.2s (10/10) FINISHED
- => [internal] load build definition from Dockerfile 0.0s
- => => transferring dockerfile: 285B 0.0s
- => [internal] load .dockerignore 0.0s
- => [internal] load metadata for docker.io/library/node:18-... 1.2s
- => [1/5] FROM docker.io/library/node:18-alpine@sha256:... 5.3s
- => [internal] load build context 0.1s
- => => transferring context: 2.45kB 0.0s
- => [2/5] WORKDIR /app 0.2s
- => [3/5] COPY package*.json ./ 0.0s
- => [4/5] RUN npm install --production 35.8s
- => [5/5] COPY . . 0.1s
- => exporting to image 2.5s
- => => exporting layers 2.5s
- => => writing image sha256:abc123... 0.0s
- => => naming to docker.io/library/my-nodejs-app:1.0 0.0s
复制代码
验证镜像:- # 查看镜像列表
- docker images | grep my-nodejs-app
复制代码
预期输出:- my-nodejs-app 1.0 abc123def456 2 minutes ago 180MB
复制代码
常见错误 ⚠️
❌ 错误1:- ERROR [3/5] COPY package*.json ./
复制代码 原因:构建上下文路径错误
解决:确保在项目根目录执行构建命令
❌ 错误2:失败- npm ERR! network request failed
复制代码 原因:网络问题或npm源问题
解决:- # 在RUN npm install前添加
- RUN npm config set registry https://registry.npmmirror.com
复制代码
❌ 错误3:构建很慢
原因:未使用国内镜像源
解决:配置Docker镜像加速器(参考Day 2)
✅ 检查点:成功构建镜像,docker images可以看到新镜像
━━━━━━━━━━━━━━━━━━━━
步骤4:运行容器并测试
目标:启动容器并验证应用功能
运行容器:- # 运行容器
- docker run -d \
- --name nodejs-demo \
- -p 3000:3000 \
- my-nodejs-app:1.0
- # 参数说明:
- # -d: 后台运行
- # --name: 容器名称
- # -p 3000:3000: 端口映射(主机:容器)
- # my-nodejs-app:1.0: 使用的镜像
复制代码
查看容器状态:- # 查看运行中的容器
- docker ps
- # 查看容器日志
- docker logs nodejs-demo
复制代码
预期日志输出:- 🚀 Server running on http://0.0.0.0:3000
- 📝 Environment: development
复制代码
测试应用:- # 测试健康检查接口
- curl http://localhost:3000/api/health
- # 测试信息接口
- curl http://localhost:3000/api/info
- # 或在浏览器打开
- # http://localhost:3000
复制代码
预期API响应:- // /api/health
- {
- "status": "healthy",
- "timestamp": "2024-01-15T10:30:00.000Z",
- "environment": "development"
- }
- // /api/info
- {
- "app": "Docker Node.js Demo",
- "version": "1.0.0",
- "node": "v18.19.0",
- "platform": "linux"
- }
复制代码
进入容器内部:- # 进入容器shell
- docker exec -it nodejs-demo sh
- # 在容器内执行命令
- pwd # 查看当前目录
- ls -la # 查看文件
- ps aux # 查看进程
- exit # 退出容器
复制代码
🎉 恭喜! 你已经成功完成了第一个Dockerfile的编写和镜像构建!
━━━━━━━━━━━━━━━━━━━━
步骤5:优化Dockerfile
目标:使用最佳实践优化镜像大小和构建速度
创建.dockerignore文件:- cat > .dockerignore << 'EOF'
- node_modules
- npm-debug.log
- .git
- .gitignore
- README.md
- .env
- .DS_Store
- *.md
- .vscode
- coverage
- .npm
- EOF
复制代码
创建优化版Dockerfile:- cat > Dockerfile.optimized << 'EOF'
- # 使用多阶段构建
- FROM node:18-alpine AS builder
- # 设置工作目录
- WORKDIR /app
- # 复制依赖文件
- COPY package*.json ./
- # 安装所有依赖(包括devDependencies)
- RUN npm ci --only=production && npm cache clean --force
- # 最终镜像
- FROM node:18-alpine
- # 添加元数据标签
- LABEL maintainer="your-email@example.com"
- LABEL version="1.0"
- LABEL description="Docker Node.js Demo Application"
- # 创建非root用户
- RUN addgroup -g 1001 -S nodejs && \
- adduser -S nodejs -u 1001
- # 设置工作目录
- WORKDIR /app
- # 从builder阶段复制依赖
- COPY --from=builder /app/node_modules ./node_modules
- # 复制应用代码
- COPY --chown=nodejs:nodejs . .
- # 切换到非root用户
- USER nodejs
- # 暴露端口
- EXPOSE 3000
- # 健康检查
- HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
- CMD node -e "require('http').get('http://localhost:3000/api/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"
- # 启动命令
- CMD ["node", "src/server.js"]
- EOF
复制代码
优化要点说明:
多阶段构建
分离构建环境和运行环境
减小最终镜像体积
使用npm ci- RUN npm ci --only=production && npm cache clean --force
复制代码 :更快、更可靠的安装方式
:只安装生产依赖
:清理缓存
创建非root用户- RUN adduser -S nodejs -u 1001
- USER nodejs
复制代码 提高容器安全性
避免使用root权限运行应用
添加健康检查- HEALTHCHECK --interval=30s --timeout=3s \
- CMD node -e "..."
复制代码 自动检测容器健康状态
便于容器编排系统管理
构建优化版镜像:- # 构建优化版镜像
- docker build -f Dockerfile.optimized -t my-nodejs-app:1.1-optimized .
- # 对比镜像大小
- docker images | grep my-nodejs-app
复制代码
预期对比:- my-nodejs-app 1.1-optimized xyz789 1 minute ago 125MB
- my-nodejs-app 1.0 abc123 10 minutes ago 180MB
复制代码
性能对比测试:- # 停止旧容器
- docker stop nodejs-demo
- docker rm nodejs-demo
- # 运行优化版
- docker run -d \
- --name nodejs-demo-v2 \
- -p 3000:3000 \
- my-nodejs-app:1.1-optimized
- # 查看健康状态
- docker ps
- # STATUS列会显示健康状态
复制代码
✅ 检查点:优化版镜像体积减小30%以上,安全性提升
━━━━━━━━━━━━━━━━━━━━
💻 完整代码
为了方便你快速上手,这里提供完整的项目结构和配置文件。
目录结构
- day08-nodejs-app/
- ├── Dockerfile # 基础版Dockerfile
- ├── Dockerfile.optimized # 优化版Dockerfile
- ├── .dockerignore # Docker忽略文件
- ├── package.json # Node.js依赖配置
- ├── docker-compose.yml # 容器编排配置
- ├── public/
- │ └── index.html # 前端页面
- └── src/
- └── server.js # 应用主文件
复制代码
docker-compose.yml
- version: '3.8'
- services:
- app:
- build:
- context: .
- dockerfile: Dockerfile.optimized
- image: my-nodejs-app:1.1-optimized
- container_name: nodejs-demo
- ports:
- - "3000:3000"
- environment:
- - NODE_ENV=production
- - PORT=3000
- restart: unless-stopped
- healthcheck:
- test: ["CMD", "node", "-e", "require('http').get('http://localhost:3000/api/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"]
- interval: 30s
- timeout: 3s
- retries: 3
- start_period: 5s
- networks:
- - app-network
- networks:
- app-network:
- driver: bridge
复制代码
Makefile(便捷操作)
- cat > Makefile << 'EOF'
- .PHONY: build run stop clean logs shell test
- # 构建镜像
- build:
- docker build -f Dockerfile.optimized -t my-nodejs-app:1.1-optimized .
- # 使用docker-compose启动
- up:
- docker-compose up -d
- # 停止服务
- down:
- docker-compose down
- # 查看日志
- logs:
- docker-compose logs -f
- # 进入容器
- shell:
- docker exec -it nodejs-demo sh
- # 测试应用
- test:
- @echo "Testing health endpoint..."
- @curl -s http://localhost:3000/api/health | jq
- @echo "\nTesting info endpoint..."
- @curl -s http://localhost:3000/api/info | jq
- # 清理资源
- clean:
- docker-compose down -v
- docker rmi my-nodejs-app:1.1-optimized
- # 重新构建并启动
- rebuild: clean build up
- @echo "✅ Rebuild complete!"
- EOF
复制代码
一键运行脚本
- cat > run.sh << 'EOF'
- #!/bin/bash
- set -e
- echo "🐳 Docker Node.js Demo - 一键启动脚本"
- echo "===================================="
- # 检查Docker是否运行
- if ! docker info > /dev/null 2>&1; then
- echo "❌ Docker未运行,请先启动Docker"
- exit 1
- fi
- # 构建镜像
- echo "📦 构建Docker镜像..."
- docker build -f Dockerfile.optimized -t my-nodejs-app:1.1-optimized .
- # 停止并删除旧容器
- echo "🧹 清理旧容器..."
- docker stop nodejs-demo 2>/dev/null || true
- docker rm nodejs-demo 2>/dev/null || true
- # 启动容器
- echo "🚀 启动容器..."
- docker run -d \
- --name nodejs-demo \
- -p 3000:3000 \
- -e NODE_ENV=production \
- my-nodejs-app:1.1-optimized
- # 等待服务启动
- echo "⏳ 等待服务启动..."
- sleep 3
- # 检查容器状态
- if docker ps | grep -q nodejs-demo; then
- echo "✅ 服务启动成功!"
- echo ""
- echo "📍 访问地址:"
- echo " Web界面: http://localhost:3000"
- echo " 健康检查: http://localhost:3000/api/health"
- echo " 应用信息: http://localhost:3000/api/info"
- echo ""
- echo "📝 查看日志: docker logs -f nodejs-demo"
- echo "🔍 进入容器: docker exec -it nodejs-demo sh"
- echo "🛑 停止服务: docker stop nodejs-demo"
- else
- echo "❌ 服务启动失败,查看日志:"
- docker logs nodejs-demo
- exit 1
- fi
- EOF
- chmod +x run.sh
复制代码
使用方法:- # 方式1: 使用一键脚本
- ./run.sh
- # 方式2: 使用Makefile
- make build # 构建镜像
- make up # 启动服务
- make logs # 查看日志
- make test # 测试接口
- make down # 停止服务
- # 方式3: 使用docker-compose
- docker-compose up -d
- docker-compose logs -f
- docker-compose down
复制代码
📦 代码仓库:GitHub - docker-30days-day08
━━━━━━━━━━━━━━━━━━━━
🚀 进阶实践
掌握了基础操作后,试试这些进阶玩法:
实践1:添加环境变量配置
目标:通过环境变量管理应用配置
提示:
创建文件存储环境变量
在Dockerfile中使用指令设置默认值
使用指令接收构建参数
在docker run时使用或传递变量
参考代码片段:- # Dockerfile中
- ARG NODE_ENV=production
- ENV NODE_ENV=${NODE_ENV}
- ENV APP_PORT=3000
- # 运行时
- docker run -e NODE_ENV=development -e APP_PORT=8080 ...
复制代码
检查清单:
[ ] 应用能读取环境变量
[ ] 不同环境使用不同配置
[ ] 敏感信息不写入镜像
━━━━━━━━━━━━━━━━━━━━
实践2:实现热重载开发环境
目标:创建开发版Dockerfile,支持代码热重载
建议:
创建使用volume挂载代码目录
安装nodemon实现自动重启
配置不同的启动命令
思路提示:- # Dockerfile.dev
- FROM node:18-alpine
- WORKDIR /app
- COPY package*.json ./
- RUN npm install # 安装包括devDependencies
- COPY . .
- CMD ["npm", "run", "dev"]
复制代码- # 运行开发环境
- docker run -v $(pwd):/app -p 3000:3000 my-app:dev
复制代码
验证方式:
修改代码文件
容器内应用自动重启
无需重新构建镜像
━━━━━━━━━━━━━━━━━━━━
实践3:构建生产级多架构镜像
目标:构建支持AMD64和ARM64的多架构镜像
挑战任务:
使用构建多架构镜像
支持Linux/AMD64和Linux/ARM64
推送到Docker Hub
参考命令:- # 创建builder
- docker buildx create --name multiarch --use
- # 构建多架构镜像
- docker buildx build \
- --platform linux/amd64,linux/arm64 \
- -t username/my-nodejs-app:1.1 \
- --push .
复制代码
资源:
Docker Buildx文档
多架构镜像最佳实践
💡 提示:完成这些实践后,在评论区分享你的成果和遇到的问题!
━━━━━━━━━━━━━━━━━━━━
🐛 故障排查
问题1:COPY失败 - no such file or directory
症状:- ERROR [4/6] COPY package*.json ./
- failed to compute cache key: "/package.json" not found
复制代码
原因:构建上下文中找不到文件
解决方案:
检查1:确认当前目录- pwd # 确保在项目根目录
- ls # 确认package.json存在
复制代码
检查2:检查.dockerignore- cat .dockerignore
- # 确保没有排除package.json
复制代码
检查3:指定构建上下文- # 明确指定上下文路径
- docker build -t my-app:1.0 -f Dockerfile .
复制代码
━━━━━━━━━━━━━━━━━━━━
问题2:npm install失败或很慢
症状:- npm ERR! network Socket timeout
- npm ERR! network This is a problem related to network connectivity.
复制代码
原因:npm默认源在国外,网络不稳定
解决方案:
方法1:在Dockerfile中配置npm镜像源- # 在RUN npm install之前添加
- RUN npm config set registry https://registry.npmmirror.com
复制代码
方法2:使用.npmrc文件- cat > .npmrc << 'EOF'
- registry=https://registry.npmmirror.com
- EOF
复制代码
方法3:使用国内基础镜像- # 使用阿里云Node.js镜像
- FROM registry.cn-hangzhou.aliyuncs.com/acs/node:18-alpine
复制代码
━━━━━━━━━━━━━━━━━━━━
问题3:容器启动后立即退出
症状:- docker ps # 看不到容器
- docker ps -a # 状态显示Exited (1)
复制代码
排查步骤:
步骤1:查看容器日志
常见错误日志和解决方案:
- # 错误1: 端口被占用
- Error: listen EADDRINUSE: address already in use :::3000
- # 解决:更换端口或关闭占用进程
- # 错误2: 模块未找到
- Error: Cannot find module 'express'
- # 解决:检查npm install是否成功
- # 错误3: 权限问题
- Error: EACCES: permission denied
- # 解决:检查文件权限或用户配置
复制代码
步骤2:交互式运行容器调试- # 使用bash进入容器调试
- docker run -it --rm my-nodejs-app:1.0 sh
- # 在容器内手动启动应用
- node src/server.js
复制代码
步骤3:检查CMD配置- # 确保CMD格式正确
- CMD ["node", "src/server.js"] # ✅ 推荐
- CMD node src/server.js # ❌ 不推荐
复制代码
━━━━━━━━━━━━━━━━━━━━
问题4:镜像体积过大
症状:
优化方案:
优化1:使用alpine基础镜像- FROM node:18-alpine # ~180MB
- # 而不是
- FROM node:18 # ~900MB
复制代码
优化2:多阶段构建- FROM node:18-alpine AS builder
- RUN npm install
- FROM node:18-alpine
- COPY --from=builder /app/node_modules ./node_modules
复制代码
优化3:清理缓存和临时文件- RUN npm install --production \
- && npm cache clean --force \
- && rm -rf /tmp/*
复制代码
优化4:使用.dockerignore- # .dockerignore
- node_modules
- .git
- *.md
- .env
- tests
复制代码
查看镜像分层:- # 分析镜像构成
- docker history my-nodejs-app:1.0
- # 使用dive工具深度分析
- docker run --rm -it \
- -v /var/run/docker.sock:/var/run/docker.sock \
- wagoodman/dive:latest my-nodejs-app:1.0
复制代码
━━━━━━━━━━━━━━━━━━━━
问题5:构建缓存问题
症状:代码修改后,构建使用了旧缓存
理解缓存机制:
Docker按层缓存
某层变化会使后续层缓存失效
COPY指令会比较文件校验和
强制重新构建:- # 不使用缓存
- docker build --no-cache -t my-app:1.0 .
- # 指定从某个阶段开始不用缓存
- docker build --target builder --no-cache -t my-app:1.0 .
复制代码
优化COPY顺序:- # ❌ 不好的做法 - 代码变化会重装依赖
- COPY . .
- RUN npm install
- # ✅ 好的做法 - 依赖不变时使用缓存
- COPY package*.json ./
- RUN npm install
- COPY . .
复制代码
━━━━━━━━━━━━━━━━━━━━
更多问题?
如果遇到其他问题:
查看 Docker官方文档 - Dockerfile参考
搜索 Docker官方论坛
查阅 Node.js Docker最佳实践
在评论区留言详细描述问题
加入学习群与大家讨论
━━━━━━━━━━━━━━━━━━━━
📚 知识点回顾
今天我们通过实践学习了:
核心Dockerfile指令
| 指令 | 作用 | 最佳实践 |
|------|------|----------|
|| 指定基础镜像 | 优先使用alpine版本 |
|| 设置工作目录 | 使用绝对路径 |
|| 复制文件 | 先复制依赖文件,利用缓存 |
|| 执行构建命令 | 合并命令减少层数 |
|| 声明端口 | 仅文档作用,不实际映射 |
|| 启动命令 | 使用JSON数组格式 |
|| 环境变量 | 设置运行时配置 |
|| 构建参数 | 设置构建时变量 |
|| 切换用户 | 生产环境避免root |
|| 健康检查 | 便于容器编排 |
关键概念总结
镜像分层原理
每个指令创建一层
层是只读的
利用缓存加速构建
构建上下文
指定的目录
包含Dockerfile和所需文件
使用.dockerignore排除不需要的文件
多阶段构建
分离构建环境和运行环境
显著减小镜像体积
提高安全性
CMD vs ENTRYPOINT
CMD:容器默认执行的命令(可被覆盖)
ENTRYPOINT:容器入口点(不易被覆盖)
组合使用实现灵活配置
Dockerfile最佳实践
✅ DO - 推荐做法
使用官方基础镜像
选择体积小的alpine版本
合并RUN指令减少层数
利用构建缓存,先复制依赖文件
使用.dockerignore排除不需要的文件
创建非root用户运行应用
添加健康检查
使用多阶段构建
❌ DON'T - 避免做法
在镜像中存储敏感信息
使用latest标签作为基础镜像
安装不必要的软件包
以root用户运行应用
每个指令都新建一层
忽略清理临时文件和缓存
完整工作流程
- graph LR
- A[编写应用代码] --> B[创建Dockerfile]
- B --> C[构建镜像]
- C --> D[运行容器]
- D --> E[测试验证]
- E --> F{是否通过}
- F -->|否| G[修改优化]
- G --> B
- F -->|是| H[推送镜像]
- H --> I[生产部署]
复制代码
下一步学习
完成今天的实践后,建议:
巩固练习
用不同语言(Python、Java、Go)编写Dockerfile
尝试容器化现有项目
实践多阶段构建
扩展阅读
Day 9:Docker镜像优化技巧
Day 10:Docker网络详解
Day 11:数据持久化与Volume
实战项目
构建完整的微服务应用
实现CI/CD自动构建
配置生产环境部署
━━━━━━━━━━━━━━━━━━━━
💬 作业时间
今日挑战:
✅ 完成文章中的所有步骤,成功运行Node.js容器
🎯 使用Dockerfile.optimized构建优化版镜像
🚀 完成至少1个进阶实践任务
📸 截图分享你的运行结果
思考题:
为什么要分两次COPY?先复制package.json再复制代码有什么好处?
CMD和ENTRYPOINT的区别是什么?什么时候用哪个?
如何让镜像体积更小?至少说出3种方法
实战任务:
尝试为你熟悉的应用(Python Flask、Java Spring Boot等)编写Dockerfile,并分享遇到的问题
讨论话题:
在容器化过程中,你觉得最容易犯的错误是什么?如何避免?
在评论区分享你的:
✅ 实践成果截图(docker images、docker ps)
💡 遇到的问题和解决方案
🎯 进阶实践的心得体会
📝 对Dockerfile的理解
优秀作业奖励:
🏆 精选作业会获得详细点评
🎁 有机会获得Docker学习资料包
👥 邀请加入技术交流群
━━━━━━━━━━━━━━━━━━━━
🔗 相关资源
官方文档 📚
Dockerfile参考文档
Docker最佳实践指南
Node.js Docker最佳实践
推荐工具 🛠️
Dive:镜像分析工具
Hadolint:Dockerfile代码检查
Docker Slim:自动优化镜像
学习资源 📖
Docker官方教程
Docker从入门到实践
12-Factor App:云原生应用设计原则
━━━━━━━━━━━━━━━━━━━━
下期预告 🔮
Day 9 - Dockerfile最佳实践与镜像优化技巧
我们将深入学习:
🎯 10个Dockerfile编写黄金法则
🚀 镜像体积优化:从500MB到50MB
🔒 容器安全最佳实践
⚡ 构建速度优化技巧
📊 镜像分析与诊断工具
敬请期待!记得点赞、收藏、关注三连哦~ 🎉

━━━━━━━━━━━━━━━━━━━━
版权声明
本文为「Docker 30天实战系列」原创内容
✅ 欢迎转发分享
✅ 转载请注明出处
❌ 禁止商业用途
━━━━━━━━━━━━━━━━━━━━
如果这篇文章对你有帮助,请点个「在看」让更多人看到! ❤️ |
|