Web应用容器化 #

容器化流程 #

基本步骤 #

text
┌─────────────────────────────────────────────────────┐
│                 容器化流程                           │
├─────────────────────────────────────────────────────┤
│                                                     │
│  1. 编写Dockerfile                                  │
│  2. 构建镜像                                        │
│  3. 本地测试                                        │
│  4. 推送镜像                                        │
│  5. 部署运行                                        │
│                                                     │
└─────────────────────────────────────────────────────┘

Nginx静态网站 #

项目结构 #

text
nginx-app/
├── Dockerfile
├── nginx.conf
└── html/
    └── index.html

Dockerfile #

dockerfile
FROM nginx:alpine

# 复制配置文件
COPY nginx.conf /etc/nginx/nginx.conf

# 复制静态文件
COPY html/ /usr/share/nginx/html/

# 暴露端口
EXPOSE 80

# 健康检查
HEALTHCHECK --interval=30s --timeout=3s \
  CMD curl -f http://localhost/ || exit 1

# 启动Nginx
CMD ["nginx", "-g", "daemon off;"]

nginx.conf #

nginx
worker_processes auto;

events {
    worker_connections 1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
    
    sendfile        on;
    keepalive_timeout  65;
    
    gzip on;
    gzip_types text/plain text/css application/json application/javascript;
    
    server {
        listen 80;
        server_name localhost;
        
        location / {
            root /usr/share/nginx/html;
            index index.html index.htm;
        }
        
        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
            root /usr/share/nginx/html;
        }
    }
}

构建和运行 #

bash
# 构建镜像
docker build -t my-nginx:v1.0 .

# 运行容器
docker run -d -p 80:80 --name my-nginx my-nginx:v1.0

# 测试
curl http://localhost

Node.js应用 #

项目结构 #

text
nodejs-app/
├── Dockerfile
├── package.json
├── src/
│   └── index.js
└── .dockerignore

Dockerfile #

dockerfile
# 构建阶段
FROM node:18-alpine AS builder

WORKDIR /app

# 复制依赖文件
COPY package*.json ./
RUN npm ci --only=production

# 运行阶段
FROM node:18-alpine

WORKDIR /app

# 复制依赖
COPY --from=builder /app/node_modules ./node_modules

# 复制源代码
COPY src/ ./src/

# 创建非root用户
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser

# 暴露端口
EXPOSE 3000

# 健康检查
HEALTHCHECK --interval=30s --timeout=3s \
  CMD curl -f http://localhost:3000/health || exit 1

# 启动应用
CMD ["node", "src/index.js"]

package.json #

json
{
  "name": "nodejs-app",
  "version": "1.0.0",
  "main": "src/index.js",
  "scripts": {
    "start": "node src/index.js"
  },
  "dependencies": {
    "express": "^4.18.2"
  }
}

index.js #

javascript
const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;

app.get('/', (req, res) => {
  res.json({ message: 'Hello Docker!' });
});

app.get('/health', (req, res) => {
  res.status(200).send('OK');
});

app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});

.dockerignore #

text
node_modules
npm-debug.log
Dockerfile
.dockerignore
.git
.gitignore
*.md
.env

构建和运行 #

bash
# 构建镜像
docker build -t my-nodejs:v1.0 .

# 运行容器
docker run -d -p 3000:3000 --name my-nodejs my-nodejs:v1.0

# 测试
curl http://localhost:3000

前端应用 #

项目结构 #

text
frontend-app/
├── Dockerfile
├── nginx.conf
├── package.json
└── src/
    └── ...

Dockerfile #

dockerfile
# 构建阶段
FROM node:18-alpine AS builder

WORKDIR /app

# 复制依赖文件
COPY package*.json ./
RUN npm ci

# 复制源代码
COPY . .

# 构建
RUN npm run build

# 运行阶段
FROM nginx:alpine

# 复制nginx配置
COPY nginx.conf /etc/nginx/nginx.conf

# 复制构建产物
COPY --from=builder /app/dist /usr/share/nginx/html

# 暴露端口
EXPOSE 80

# 启动Nginx
CMD ["nginx", "-g", "daemon off;"]

构建和运行 #

bash
# 构建镜像
docker build -t my-frontend:v1.0 .

# 运行容器
docker run -d -p 80:80 --name my-frontend my-frontend:v1.0

Python Web应用 #

项目结构 #

text
python-app/
├── Dockerfile
├── requirements.txt
├── app.py
└── .dockerignore

Dockerfile #

dockerfile
FROM python:3.11-slim

WORKDIR /app

# 安装依赖
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 复制源代码
COPY app.py .

# 创建非root用户
RUN useradd -m appuser
USER appuser

# 暴露端口
EXPOSE 8000

# 健康检查
HEALTHCHECK --interval=30s --timeout=3s \
  CMD curl -f http://localhost:8000/health || exit 1

# 启动应用
CMD ["python", "app.py"]

app.py #

python
from flask import Flask, jsonify

app = Flask(__name__)

@app.route('/')
def index():
    return jsonify({'message': 'Hello Docker!'})

@app.route('/health')
def health():
    return 'OK', 200

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8000)

requirements.txt #

text
flask==3.0.0
gunicorn==21.2.0

构建和运行 #

bash
# 构建镜像
docker build -t my-python:v1.0 .

# 运行容器
docker run -d -p 8000:8000 --name my-python my-python:v1.0

# 测试
curl http://localhost:8000

Docker Compose部署 #

docker-compose.yml #

yaml
version: '3.8'

services:
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./html:/usr/share/nginx/html:ro
    depends_on:
      - app

  app:
    build:
      context: ./app
      dockerfile: Dockerfile
    environment:
      - NODE_ENV=production
      - DB_HOST=db
    depends_on:
      - db

  db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: mydb
    volumes:
      - mysql-data:/var/lib/mysql

volumes:
  mysql-data:

部署命令 #

bash
# 启动服务
docker-compose up -d

# 查看状态
docker-compose ps

# 查看日志
docker-compose logs -f

# 停止服务
docker-compose down

小结 #

本节学习了Web应用的容器化:

  • Nginx静态网站容器化
  • Node.js应用容器化
  • 前端应用容器化
  • Python Web应用容器化
  • Docker Compose部署

下一步 #

接下来,让我们学习 微服务架构部署,了解微服务的容器化部署。