openEuler容器化实践:从Docker入门到生产部署

一、引言

容器技术已经成为现代软件开发和部署的标准实践。相比传统虚拟机,容器具有轻量级、启动快速、资源利用率高、环境一致性好等显著优势。Docker作为容器技术的代表,已经在DevOps、微服务架构、持续集成等场景中得到广泛应用。

openEuler作为面向企业级应用的开源操作系统,对容器技术提供了完善的支持。除了兼容Docker之外,openEuler还自主研发了iSula轻量级容器引擎,在启动速度、内存占用等方面表现优异。特别是在WSL2环境下,openEuler能够无缝运行Docker,为开发者提供与Linux服务器一致的容器化开发体验。

本文将基于openEuler 24.03 LTS版本,系统介绍容器化技术的完整实践。从Docker的安装配置、镜像构建、容器管理,到多容器编排、网络配置、数据持久化,再到实际应用的容器化改造和生产部署,全面覆盖容器化技术栈。通过实际操作和最佳实践,帮助开发者掌握在openEuler上进行容器化开发和部署的完整流程。

二、Docker环境搭建

2.1 Docker安装

openEuler 24.03已经内置了Docker支持,安装非常简单:

bash 复制代码
# 检查系统版本
cat /etc/os-release

# 安装Docker
sudo dnf install -y docker

# 启动Docker服务
sudo systemctl start docker
sudo systemctl enable docker

# 验证安装
docker --version
# Docker version 20.10.x

# 查看Docker信息
docker info

# 运行hello-world测试
sudo docker run hello-world

2.2 配置Docker权限

默认情况下需要sudo才能运行docker命令,我们可以添加用户到docker组:

bash 复制代码
# 创建docker组(如果不存在)
sudo groupadd docker

# 将当前用户添加到docker组
sudo usermod -aG docker $USER

# 重新登录或刷新组权限
newgrp docker

# 验证(无需sudo)
docker ps

# 测试
docker run hello-world

2.3 配置Docker镜像加速

使用国内镜像源可以大幅提升镜像拉取速度:

创建Docker配置目录

bash 复制代码
# 创建Docker配置目录
sudo mkdir -p /etc/docker

# 配置镜像加速
sudo tee /etc/docker/daemon.json > /dev/null << 'EOF'
{
  "registry-mirrors": [
    "https://mirror.ccs.tencentyun.com",
    "https://docker.mirrors.ustc.edu.cn",
    "https://hub-mirror.c.163.com"
  ],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  },
  "storage-driver": "overlay2"
}
EOF

# 重启Docker服务
sudo systemctl daemon-reload
sudo systemctl restart docker

# 验证配置
docker info | grep -A 5 "Registry Mirrors"

三、Docker基础操作

3.1 镜像操作

bash 复制代码
# 搜索镜像
docker search nginx

# 拉取镜像
docker pull nginx:latest
docker pull python:3.11-alpine
docker pull ubuntu:22.04

# 列出本地镜像
docker images

# 查看镜像详细信息
docker inspect nginx:latest

# 删除镜像
docker rmi image_name:tag

# 导出镜像
docker save -o nginx.tar nginx:latest

# 导入镜像
docker load -i nginx.tar

# 给镜像打标签
docker tag nginx:latest myregistry.com/nginx:v1.0

# 清理悬空镜像
docker image prune

3.2 容器操作

bash 复制代码
# 运行容器
docker run -d --name mynginx -p 8080:80 nginx

# 参数说明:
# -d: 后台运行
# --name: 指定容器名称
# -p: 端口映射 host:container

# 列出运行中的容器
docker ps

# 列出所有容器(包括已停止)
docker ps -a

# 查看容器日志
docker logs mynginx
docker logs -f mynginx  # 实时输出

# 进入容器
docker exec -it mynginx bash

# 停止容器
docker stop mynginx

# 启动容器
docker start mynginx

# 重启容器
docker restart mynginx

# 删除容器
docker rm mynginx

# 强制删除运行中的容器
docker rm -f mynginx

# 查看容器详细信息
docker inspect mynginx

# 查看容器资源使用
docker stats mynginx

# 容器与主机文件复制
docker cp mynginx:/etc/nginx/nginx.conf ./
docker cp ./index.html mynginx:/usr/share/nginx/html/

3.3 常用容器运行案例

运行Nginx Web服务器

bash 复制代码
docker run -d \
  --name web \
  -p 8080:80 \
  -v $(pwd)/html:/usr/share/nginx/html:ro \
  --restart=always \
  nginx:alpine

# 访问测试
curl http://localhost:8080

运行MySQL数据库

ini 复制代码
docker run -d \
  --name mysql \
  -p 3306:3306 \
  -e MYSQL_ROOT_PASSWORD=rootpass \
  -e MYSQL_DATABASE=mydb \
  -v mysql_data:/var/lib/mysql \
  --restart=always \
  mysql:8.0

# 连接测试
docker exec -it mysql mysql -uroot -prootpass

连接测试

bash 复制代码
docker run -d \
  --name redis \
  -p 6379:6379 \
  -v redis_data:/data \
  --restart=always \
  redis:alpine redis-server --appendonly yes

# 测试连接
docker exec -it redis redis-cli ping

四、Dockerfile镜像构建

4.1 Dockerfile基础语法

ini 复制代码
# Dockerfile示例
# 基础镜像
FROM python:3.11-slim

# 维护者信息
LABEL maintainer="your.email@example.com"
LABEL version="1.0"
LABEL description="Python Flask应用"

# 设置环境变量
ENV PYTHONUNBUFFERED=1 \
    APP_HOME=/app

# 设置工作目录
WORKDIR $APP_HOME

# 复制依赖文件
COPY requirements.txt .

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

# 复制应用代码
COPY . .

# 暴露端口
EXPOSE 5000

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

# 启动命令
CMD ["python", "app.py"]

4.2 构建Python Flask应用镜像

项目结构

复制代码
flask_app/
├── Dockerfile
├── requirements.txt
├── app.py
└── templates/
    └── index.html

app.py

python 复制代码
from flask import Flask, jsonify, render_template
import os
import socket

app = Flask(__name__)

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/api/info')
def info():
    return jsonify({
        'hostname': socket.gethostname(),
        'python_version': os.sys.version,
        'env': os.environ.get('ENVIRONMENT', 'development')
    })

@app.route('/health')
def health():
    return jsonify({'status': 'healthy'}), 200

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

requirements.txt

ini 复制代码
Flask==3.0.0
gunicorn==21.2.0

Dockerfile

bash 复制代码
FROM python:3.11-slim

# 安装系统依赖
RUN apt-get update && \
    apt-get install -y --no-install-recommends curl && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

EXPOSE 5000

HEALTHCHECK CMD curl -f http://localhost:5000/health || exit 1

CMD ["gunicorn", "-b", "0.0.0.0:5000", "-w", "4", "app:app"]

构建和运行

bash 复制代码
# 构建镜像
docker build -t myapp:1.0 .

# 查看构建的镜像
docker images | grep myapp

# 运行容器
docker run -d \
  --name myapp \
  -p 5000:5000 \
  -e ENVIRONMENT=production \
  myapp:1.0

# 测试应用
curl http://localhost:5000/api/info

# 查看日志
docker logs -f myapp

4.3 多阶段构建优化

多阶段构建可以显著减小镜像大小:

bash 复制代码
# 第一阶段:构建
FROM python:3.11 as builder

WORKDIR /build

COPY requirements.txt .
RUN pip install --user --no-cache-dir -r requirements.txt

# 第二阶段:运行
FROM python:3.11-slim

WORKDIR /app

# 从构建阶段复制依赖
COPY --from=builder /root/.local /root/.local

# 复制应用代码
COPY . .

# 确保pip安装的包在PATH中
ENV PATH=/root/.local/bin:$PATH

EXPOSE 5000

CMD ["python", "app.py"]

对比效果

perl 复制代码
# 单阶段构建
docker build -t myapp:single .
docker images | grep myapp
# myapp single 850MB

# 多阶段构建
docker build -t myapp:multi -f Dockerfile.multi .
docker images | grep myapp
# myapp multi 180MB

五、Docker Compose多容器编排

5.1 安装Docker Compose

bash 复制代码
# 下载Docker Compose
sudo curl -L "https://github.com/docker/compose/releases/download/v2.23.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

# 添加执行权限
sudo chmod +x /usr/local/bin/docker-compose

# 验证安装
docker-compose --version
# Docker Compose version v2.23.0

5.2 Web应用完整栈

项目结构

webapp/

├── docker-compose.yml

├── nginx/

│ └── nginx.conf

├── backend/

│ ├── Dockerfile

│ ├── app.py

│ └── requirements.txt

└── frontend/

├── Dockerfile

└── index.html

docker-compose.yml

yaml 复制代码
version: '3.8'

services:
  # 数据库
  db:
    image: postgres:15-alpine
    container_name: webapp_db
    environment:
      POSTGRES_DB: webapp
      POSTGRES_USER: dbuser
      POSTGRES_PASSWORD: dbpass
    volumes:
      - postgres_data:/var/lib/postgresql/data
    networks:
      - backend
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U dbuser"]
      interval: 10s
      timeout: 5s
      retries: 5

  # Redis缓存
  redis:
    image: redis:alpine
    container_name: webapp_redis
    networks:
      - backend
    command: redis-server --appendonly yes
    volumes:
      - redis_data:/data

  # 后端API
  backend:
    build:
      context: ./backend
      dockerfile: Dockerfile
    container_name: webapp_backend
    environment:
      DATABASE_URL: postgresql://dbuser:dbpass@db:5432/webapp
      REDIS_URL: redis://redis:6379/0
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started
    networks:
      - backend
      - frontend
    restart: always

  # 前端应用
  frontend:
    build:
      context: ./frontend
      dockerfile: Dockerfile
    container_name: webapp_frontend
    networks:
      - frontend
    restart: always

  # Nginx反向代理
  nginx:
    image: nginx:alpine
    container_name: webapp_nginx
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./nginx/ssl:/etc/nginx/ssl:ro
    depends_on:
      - backend
      - frontend
    networks:
      - frontend
    restart: always

networks:
  backend:
    driver: bridge
  frontend:
    driver: bridge

volumes:
  postgres_data:
  redis_data:

nginx/nginx.conf

ini 复制代码
events {
    worker_connections 1024;
}

http {
    upstream backend {
        server backend:5000;
    }

    upstream frontend {
        server frontend:80;
    }

    server {
        listen 80;
        server_name localhost;

        # 前端
        location / {
            proxy_pass http://frontend;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }

        # 后端API
        location /api {
            proxy_pass http://backend;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }

        # 健康检查
        location /health {
            access_log off;
            return 200 "healthy\n";
            add_header Content-Type text/plain;
        }
    }
}

启动和管理

ini 复制代码
# 启动所有服务
docker-compose up -d

# 查看服务状态
docker-compose ps

# 查看日志
docker-compose logs -f

# 查看特定服务日志
docker-compose logs -f backend

# 重启服务
docker-compose restart backend

# 停止所有服务
docker-compose stop

# 停止并删除容器
docker-compose down

# 删除容器和数据卷
docker-compose down -v

# 重新构建并启动
docker-compose up -d --build

# 扩展服务实例
docker-compose up -d --scale backend=3

六、数据持久化与网络配置

6.1 数据卷管理

bash 复制代码
# 创建数据卷
docker volume create mydata

# 列出所有数据卷
docker volume ls

# 查看数据卷详情
docker volume inspect mydata

# 使用数据卷
docker run -d \
  --name app \
  -v mydata:/app/data \
  myimage

# 绑定挂载(宿主机目录)
docker run -d \
  --name app \
  -v $(pwd)/data:/app/data \
  myimage

# 只读挂载
docker run -d \
  --name app \
  -v $(pwd)/config:/app/config:ro \
  myimage

# 备份数据卷
docker run --rm \
  -v mydata:/source \
  -v $(pwd)/backup:/backup \
  alpine tar czf /backup/mydata_backup.tar.gz -C /source .

# 恢复数据卷
docker run --rm \
  -v mydata:/target \
  -v $(pwd)/backup:/backup \
  alpine tar xzf /backup/mydata_backup.tar.gz -C /target

# 删除数据卷
docker volume rm mydata

# 清理未使用的数据卷
docker volume prune

6.2 网络配置

bash 复制代码
# 创建自定义网络
docker network create mynetwork
docker network create --driver bridge --subnet=172.18.0.0/16 custom_net

# 列出网络
docker network ls

# 查看网络详情
docker network inspect mynetwork

# 连接容器到网络
docker network connect mynetwork container_name

# 断开网络连接
docker network disconnect mynetwork container_name

# 创建容器时指定网络
docker run -d \
  --name app \
  --network mynetwork \
  --network-alias app \
  myimage

# 查看容器网络配置
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container_name

# 删除网络
docker network rm mynetwork

# 清理未使用的网络
docker network prune

6.3 容器间通信示例

ini 复制代码
# 创建自定义网络
docker network create appnet

# 启动数据库容器
docker run -d \
  --name db \
  --network appnet \
  --network-alias database \
  -e POSTGRES_PASSWORD=secret \
  postgres:15

# 启动应用容器(可以通过'database'访问数据库)
docker run -d \
  --name app \
  --network appnet \
  -e DB_HOST=database \
  -e DB_PORT=5432 \
  -e DB_PASSWORD=secret \
  myapp

# 测试连接
docker exec app ping database
docker exec app nc -zv database 5432

七、实战案例:WordPress部署

7.1 使用Docker Compose部署WordPress

yaml 复制代码
# wordpress/docker-compose.yml
version: '3.8'

services:
  wordpress:
    image: wordpress:latest
    container_name: wordpress
    ports:
      - "8080:80"
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: wpuser
      WORDPRESS_DB_PASSWORD: wppass
      WORDPRESS_DB_NAME: wordpress
    volumes:
      - wordpress_data:/var/www/html
    depends_on:
      - db
    restart: always

  db:
    image: mysql:8.0
    container_name: wordpress_db
    environment:
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wpuser
      MYSQL_PASSWORD: wppass
      MYSQL_ROOT_PASSWORD: rootpass
    volumes:
      - db_data:/var/lib/mysql
    restart: always

volumes:
  wordpress_data:
  db_data:
bash 复制代码
# 启动WordPress
cd wordpress
docker-compose up -d

# 查看状态
docker-compose ps

# 访问 http://localhost:8080 完成安装

# 备份
docker-compose exec db mysqldump -u root -prootpass wordpress > wordpress_backup.sql

# 查看日志
docker-compose logs -f wordpress

八、容器监控与日志管理

8.1 资源监控

bash 复制代码
# 查看所有容器资源使用
docker stats

# 查看特定容器
docker stats container_name

# 查看容器进程
docker top container_name

# 查看容器事件
docker events

# 查看容器端口映射
docker port container_name

8.2 日志管理

bash 复制代码
# 查看日志
docker logs container_name

# 实时跟踪日志
docker logs -f container_name

# 查看最近100行
docker logs --tail 100 container_name

# 查看时间范围
docker logs --since 10m container_name
docker logs --until 2024-01-01T00:00:00 container_name

# 配置日志驱动(daemon.json)
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3",
    "compress": "true"
  }
}

8.3 集成Prometheus监控

yaml 复制代码
# monitoring/docker-compose.yml
version: '3.8'

services:
  prometheus:
    image: prom/prometheus
    container_name: prometheus
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
      - prometheus_data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
    restart: always

  grafana:
    image: grafana/grafana
    container_name: grafana
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin
    volumes:
      - grafana_data:/var/lib/grafana
    depends_on:
      - prometheus
    restart: always

  cadvisor:
    image: gcr.io/cadvisor/cadvisor
    container_name: cadvisor
    ports:
      - "8090:8080"
    volumes:
      - /:/rootfs:ro
      - /var/run:/var/run:ro
      - /sys:/sys:ro
      - /var/lib/docker/:/var/lib/docker:ro
    restart: always

volumes:
  prometheus_data:
  grafana_data:

九、生产环境最佳实践

9.1 安全加固

ini 复制代码
# 使用非root用户运行
FROM python:3.11-slim

RUN useradd -m -u 1000 appuser

WORKDIR /app
COPY --chown=appuser:appuser . .

USER appuser

CMD ["python", "app.py"]


# 扫描镜像漏洞
docker scan myimage:latest

# 限制容器资源
docker run -d \
  --name app \
  --memory="512m" \
  --cpus="1.0" \
  --pids-limit=100 \
  myimage

9.2 健康检查

bash 复制代码
# Dockerfile中添加健康检查
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
  CMD curl -f http://localhost:5000/health || exit 1
  
  
  # docker-compose.yml中配置
services:
  app:
    image: myapp
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:5000/health"]
      interval: 30s
      timeout: 3s
      retries: 3
      start_period: 40s

9.3 自动重启策略

ini 复制代码
# 容器退出时总是重启
docker run -d --restart=always myimage

# 仅非正常退出时重启
docker run -d --restart=on-failure:5 myimage

# 除非手动停止,否则重启
docker run -d --restart=unless-stopped myimage

十、总结与展望

通过本次在openEuler上的容器化实践,我们全面掌握了从基础的Docker操作到生产环境部署的完整技能。openEuler提供的稳定系统环境和完善的Docker支持,为容器化应用提供了可靠的运行平台。

核心收获

  1. ✅ Docker基础操作和镜像管理
  2. ✅ Dockerfile编写和多阶段构建
  3. ✅ Docker Compose多容器编排
  4. ✅ 数据持久化和网络配置
  5. ✅ 监控日志和生产部署

下一步方向

  • Kubernetes容器编排
  • CI/CD流水线集成
  • 微服务架构实践
  • 服务网格(Service Mesh)
  • 容器安全加固

参考资源

作者声明:本文为原创技术实践文章,所有操作均在openEuler 24.03 LTS + Docker环境中验证。

相关推荐
Cache技术分享2 小时前
233. Java 集合 - 遍历 Collection 中的元素
前端·后端
回家路上绕了弯3 小时前
五分钟内重复登录 QQ 号定位:数据结构选型与高效实现方案
分布式·后端
AI三林叔3 小时前
第2章 MCP协议深度解析
后端
Felix_XXXXL3 小时前
Spring Security安全框架原理与实战
java·后端
JaguarJack3 小时前
从零开始打造 Laravel 扩展包:开发、测试到发布完整指南
后端·php·laravel
星释4 小时前
Rust 练习册 :Minesweeper与二维数组处理
开发语言·后端·rust
小蒜学长4 小时前
springboot基于Java的校园导航微信小程序的设计与实现(代码+数据库+LW)
java·spring boot·后端·微信小程序
微学AI4 小时前
基于openEuler操作系统的Docker部署与AI应用实践操作与研究
后端
王元_SmallA4 小时前
IDEA + Spring Boot 的三种热加载方案
java·后端