CentOS Stream 9 的 Docker 容器 ------ 语法详解与实战案例
系统环境:CentOS Stream 9 x86_64
Docker 版本:26.1(或 Podman 4.9)
目标:掌握容器化部署核心技能
一、云计算与容器概述
云计算:通过网络提供计算资源(CPU、内存、存储、网络)的服务模式。
三种服务模型:
| 类型 | 说明 | 示例 |
|---|---|---|
| IaaS(基础设施即服务) | 提供虚拟机、存储、网络等基础资源 | AWS EC2, Azure VM |
| PaaS(平台即服务) | 提供开发运行平台(含中间件、数据库等) | Heroku, Google App Engine |
| SaaS(软件即服务) | 直接提供应用程序 | Gmail, Office 365 |
容器技术:轻量级虚拟化,共享宿主机内核,隔离进程、文件系统、网络。
容器 vs 虚拟机:
| 对比项 | 容器 | 虚拟机 |
|---|---|---|
| 启动速度 | 秒级 | 分钟级 |
| 资源占用 | 极低 | 高(需完整 OS) |
| 隔离性 | 进程级 | 硬件级 |
| 镜像大小 | MB 级 | GB 级 |
| 适用场景 | 微服务、CI/CD、快速部署 | 完整系统模拟、强隔离需求 |
主流容器技术:
- Docker:最流行,生态完善,企业广泛使用
- Podman:Red Hat 主推,无守护进程,rootless 安全,兼容 Docker CLI
- Containerd:底层容器运行时,K8s 默认使用
本章重点:Docker + Podman 基础 + Nginx/MySQL 容器化部署
二、Docker 技术详解
2.1 Docker 核心概念
| 概念 | 说明 |
|---|---|
| 镜像(Image) | 只读模板,包含运行环境和应用程序(如 ubuntu:22.04, nginx:latest) |
| 容器(Container) | 镜像的运行实例,可启动、停止、删除 |
| 仓库(Registry) | 存储镜像的地方(Docker Hub, Harbor, 阿里云镜像仓库) |
| Dockerfile | 定义镜像构建步骤的文本文件 |
| docker-compose.yml | 定义多容器应用的编排文件 |
2.2 Docker 安装(CentOS Stream 9)
✅ 安装 Docker Engine:
bash
# 卸载旧版本(如有)
sudo dnf remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine
# 安装依赖
sudo dnf install -y dnf-plugins-core
sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# 安装 Docker Engine、CLI、Containerd
sudo dnf install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# 启动并设置开机自启
sudo systemctl start docker
sudo systemctl enable docker
# 验证安装
sudo docker run hello-world
✅ 将当前用户加入 docker 组(免 sudo):
bash
sudo usermod -aG docker $USER
newgrp docker # 立即生效组权限(或重新登录)
# 验证无需 sudo
docker run hello-world
✅ 查看版本:
bash
docker --version
docker info
2.3 Docker 常用命令语法详解
① 镜像管理
bash
# 拉取镜像
docker pull nginx:latest
# 查看本地镜像
docker images
# 删除镜像(需无容器使用)
docker rmi nginx:latest
# 构建镜像(从 Dockerfile)
docker build -t myapp:1.0 .
# 打标签
docker tag myapp:1.0 myregistry.com/myapp:1.0
# 推送镜像
docker push myregistry.com/myapp:1.0
② 容器管理
bash
# 运行容器(前台)
docker run -it ubuntu:22.04 /bin/bash
# 后台运行 + 端口映射 + 自动重启 + 命名
docker run -d \
--name mynginx \
-p 8080:80 \
--restart unless-stopped \
nginx:latest
# 查看运行中容器
docker ps
# 查看所有容器(含停止的)
docker ps -a
# 查看容器日志
docker logs mynginx
# 进入运行中的容器
docker exec -it mynginx /bin/bash
# 停止容器
docker stop mynginx
# 启动已停止容器
docker start mynginx
# 删除容器(必须先停止)
docker rm mynginx
# 强制删除运行中容器
docker rm -f mynginx
# 查看容器资源使用
docker stats mynginx
③ 数据卷与挂载
bash
# 挂载主机目录到容器
docker run -d \
--name mynginx \
-v /home/user/html:/usr/share/nginx/html \
-p 8080:80 \
nginx:latest
# 创建命名数据卷
docker volume create myvol
# 使用数据卷
docker run -d \
--name mynginx \
-v myvol:/usr/share/nginx/html \
nginx:latest
# 查看数据卷
docker volume ls
docker volume inspect myvol
④ 网络管理
bash
# 查看网络
docker network ls
# 创建自定义网络
docker network create mynet
# 容器加入自定义网络
docker run -d \
--name mynginx \
--network mynet \
nginx:latest
# 容器间通过容器名通信(需在同一网络)
docker run -it --network mynet alpine ping mynginx
2.4 Dockerfile 语法详解(带注释)
✅ 示例:构建自定义 Nginx 镜像,包含自定义首页
dockerfile
# Dockerfile
# 基础镜像
FROM nginx:latest
# 维护者信息(可选)
LABEL maintainer="admin@example.com"
# 将本地文件复制到镜像中(相对 Dockerfile 路径)
COPY index.html /usr/share/nginx/html/
# 暴露端口(文档说明,实际需 -p 映射)
EXPOSE 80
# 启动命令(Nginx 默认已设置,可省略)
# CMD ["nginx", "-g", "daemon off;"]
✅ 准备 index.html:
html
<!-- index.html -->
<!DOCTYPE html>
<html>
<head><title>My Custom Nginx</title></head>
<body>
<h1>Hello from Custom Docker Nginx!</h1>
<p>Deployed on: <%= new Date() %></p>
</body>
</html>
✅ 构建并运行:
bash
# 构建镜像(末尾 . 表示当前目录为构建上下文)
docker build -t my-nginx:1.0 .
# 运行容器
docker run -d --name myweb -p 8080:80 my-nginx:1.0
# 访问 http://localhost:8080 查看效果
✅ Dockerfile 指令速查:
| 指令 | 作用 | 示例 |
|---|---|---|
FROM |
指定基础镜像 | FROM ubuntu:22.04 |
LABEL |
添加元数据 | LABEL version="1.0" |
COPY |
复制文件到镜像 | COPY app.py /app/ |
ADD |
复制+自动解压 | ADD app.tar.gz /app/ |
RUN |
执行命令(构建时) | RUN apt update && apt install -y curl |
CMD |
容器启动默认命令 | CMD ["python", "app.py"] |
ENTRYPOINT |
入口点(不可被覆盖) | ENTRYPOINT ["./start.sh"] |
EXPOSE |
声明端口 | EXPOSE 80 |
ENV |
设置环境变量 | ENV DEBUG=true |
WORKDIR |
设置工作目录 | WORKDIR /app |
VOLUME |
声明数据卷 | VOLUME ["/data"] |
2.5 docker-compose.yml 语法详解
用于定义和运行多容器应用。
✅ 示例:同时部署 Nginx + MySQL
yaml
# docker-compose.yml
version: '3.8' # Compose 文件版本
services:
# 定义第一个服务:Web 服务器
web:
image: nginx:latest
container_name: my_nginx
ports:
- "8080:80" # 主机端口:容器端口
volumes:
- ./html:/usr/share/nginx/html # 挂载自定义页面
depends_on:
- db # 依赖 db 服务(启动顺序)
restart: unless-stopped
# 定义第二个服务:数据库
db:
image: mysql:8.0
container_name: my_mysql
environment:
MYSQL_ROOT_PASSWORD: my-secret-pw
MYSQL_DATABASE: myapp
MYSQL_USER: appuser
MYSQL_PASSWORD: app-pass
ports:
- "3306:3306"
volumes:
- mysql_data:/var/lib/mysql # 使用命名卷
restart: unless-stopped
# 定义命名卷(全局)
volumes:
mysql_data:
✅ 准备自定义页面:
bash
mkdir html
echo "<h1>Welcome to My Docker Site!</h1>" > html/index.html
✅ 启动服务:
bash
# 启动所有服务(后台)
docker-compose up -d
# 查看服务状态
docker-compose ps
# 查看日志
docker-compose logs web
docker-compose logs db
# 停止服务
docker-compose down
# 重建镜像并启动
docker-compose up -d --build
✅ docker-compose.yml 关键语法:
| 字段 | 说明 |
|---|---|
version |
Compose 文件格式版本 |
services |
定义多个容器服务 |
image |
使用的镜像 |
build |
指定 Dockerfile 路径(替代 image) |
ports |
端口映射 "主机:容器" |
volumes |
数据卷挂载 "主机路径:容器路径" 或 "命名卷:容器路径" |
environment |
设置环境变量 |
depends_on |
启动依赖顺序 |
restart |
重启策略(no, always, unless-stopped) |
volumes(根) |
定义命名卷 |
三、Podman 技术详解
Podman:Red Hat 开发,Docker CLI 兼容,无守护进程,支持 rootless,更安全。
✅ 安装 Podman(CentOS Stream 9 默认已安装):
bash
# 查看是否已安装
podman --version
# 若未安装:
sudo dnf install -y podman
# 验证
podman run hello-world
✅ Podman 与 Docker 命令对比:
| Docker | Podman | 说明 |
|---|---|---|
docker run |
podman run |
完全兼容 |
docker ps |
podman ps |
|
docker build |
podman build |
|
docker-compose |
podman-compose |
需单独安装 |
✅ 安装 podman-compose:
bash
sudo dnf install -y python3-pip
pip3 install podman-compose
✅ 使用示例(与 Docker 几乎一致):
bash
# 拉取镜像
podman pull nginx:latest
# 运行容器
podman run -d --name mypodnginx -p 8081:80 nginx:latest
# 查看容器
podman ps
# 查看镜像
podman images
# 无守护进程:直接管理容器进程,更轻量安全
✅ Rootless 模式(推荐):
bash
# 普通用户直接运行(无需 sudo)
podman run -d --name rootless-nginx -p 8082:80 nginx:latest
# 查看用户级容器
podman ps -a
# 用户级镜像存储在 ~/.local/share/containers/
✅ 与 Docker 互操作:
bash
# 导出 Docker 镜像为 tar
docker save nginx:latest > nginx.tar
# Podman 加载
podman load -i nginx.tar
# 导出 Podman 镜像
podman save nginx:latest -o nginx-podman.tar
✅ Podman 优势:
- 无 daemon,更安全,资源占用少
- 支持 rootless,普通用户可运行容器
- 与 systemd 集成好(
podman generate systemd) - 兼容 Docker CLI 和镜像格式
四、综合案例1:Nginx 容器部署
4.1 案例概述
使用 Docker 部署 Nginx Web 服务器,支持自定义页面、端口映射、数据卷挂载、自动重启。
适用场景:快速搭建静态网站、反向代理、负载均衡测试环境。
4.2 案例详解
✅ 方法一:直接运行官方镜像(快速测试)
bash
# 后台运行,映射端口,设置重启策略
docker run -d \
--name webserver \
-p 8080:80 \
--restart unless-stopped \
nginx:latest
# 验证访问
curl http://localhost:8080
# 应返回默认 Nginx 欢迎页
✅ 方法二:自定义页面 + 数据卷挂载(生产推荐)
bash
# 创建本地目录存放自定义页面
mkdir -p ~/myweb/html
echo "<h1>My Docker Nginx Site</h1>" > ~/myweb/html/index.html
# 运行容器并挂载目录
docker run -d \
--name myweb \
-p 8080:80 \
-v ~/myweb/html:/usr/share/nginx/html:ro \ # ro=只读,安全
--restart unless-stopped \
nginx:latest
# 验证自定义页面
curl http://localhost:8080
# 输出:My Docker Nginx Site
✅ 方法三:使用 Dockerfile 构建自定义镜像
dockerfile
# Dockerfile.custom
FROM nginx:alpine # 更小体积
# 删除默认欢迎页
RUN rm -f /usr/share/nginx/html/*
# 复制自定义页面
COPY ./html/ /usr/share/nginx/html/
# 暴露端口
EXPOSE 80
# 使用默认启动命令
✅ 构建并运行:
bash
# 目录结构:
# .
# ├── Dockerfile.custom
# └── html/
# └── index.html
docker build -t my-nginx-custom:1.0 -f Dockerfile.custom .
docker run -d --name custom-web -p 8080:80 my-nginx-custom:1.0
✅ 方法四:使用 docker-compose 编排(推荐用于多服务)
yaml
# docker-compose-nginx.yml
version: '3.8'
services:
nginx:
image: nginx:latest
container_name: prod_nginx
ports:
- "80:80"
volumes:
- ./html:/usr/share/nginx/html:ro
- ./nginx.conf:/etc/nginx/nginx.conf:ro # 可选:自定义配置
restart: always
networks:
- webnet
networks:
webnet:
driver: bridge
✅ 启动:
bash
docker-compose -f docker-compose-nginx.yml up -d
五、综合案例2:MySQL 容器部署
5.1 案例概述
使用 Docker 部署 MySQL 8.0 数据库,设置 root 密码、创建数据库和用户,持久化数据卷,支持远程连接。
适用场景:开发测试数据库、微服务后端存储。
5.2 案例详解
✅ 基础运行(不推荐生产)
bash
docker run -d \
--name mysql_db \
-p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=secret123 \
mysql:8.0
# 进入容器测试
docker exec -it mysql_db mysql -uroot -p
# 输入密码 secret123
✅ 生产级部署(推荐):
bash
# 创建数据卷(持久化)
docker volume create mysql_data
# 创建配置目录
mkdir -p ~/mysql/conf
mkdir -p ~/mysql/init
# 创建初始化 SQL 脚本(可选)
cat > ~/mysql/init/init.sql <<EOF
CREATE DATABASE IF NOT EXISTS myapp;
CREATE USER 'appuser'@'%' IDENTIFIED BY 'AppPass123!';
GRANT ALL PRIVILEGES ON myapp.* TO 'appuser'@'%';
FLUSH PRIVILEGES;
EOF
# 运行 MySQL 容器
docker run -d \
--name mysql_prod \
-p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=RootPass456! \
-e MYSQL_DATABASE=myapp \
-e MYSQL_USER=appuser \
-e MYSQL_PASSWORD=AppPass123! \
-v mysql_data:/var/lib/mysql \
-v ~/mysql/conf:/etc/mysql/conf.d \
-v ~/mysql/init:/docker-entrypoint-initdb.d \
--restart unless-stopped \
mysql:8.0 \
--character-set-server=utf8mb4 \
--collation-server=utf8mb4_unicode_ci
# 验证数据库
docker exec -it mysql_prod mysql -uappuser -pAppPass123! -e "SHOW DATABASES;"
✅ 关键参数说明:
-e MYSQL_ROOT_PASSWORD:设置 root 密码(必需)-e MYSQL_DATABASE:自动创建数据库-e MYSQL_USER / MYSQL_PASSWORD:创建用户并授权-v ~/mysql/init:/docker-entrypoint-initdb.d:容器首次启动时执行 SQL 脚本--character-set-server=utf8mb4:设置默认字符集
✅ 自定义 MySQL 配置(my.cnf)
ini
# ~/mysql/conf/custom.cnf
[mysqld]
max_connections=200
innodb_buffer_pool_size=256M
log-error=/var/log/mysql/error.log
slow_query_log=1
slow_query_log_file=/var/log/mysql/slow.log
long_query_time=2
✅ 使用 docker-compose 部署 MySQL(推荐)
yaml
# docker-compose-mysql.yml
version: '3.8'
services:
mysql:
image: mysql:8.0
container_name: mysql_server
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: RootPass456!
MYSQL_DATABASE: myapp
MYSQL_USER: appuser
MYSQL_PASSWORD: AppPass123!
volumes:
- mysql_data:/var/lib/mysql
- ./mysql/conf:/etc/mysql/conf.d
- ./mysql/init:/docker-entrypoint-initdb.d
command:
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
restart: unless-stopped
volumes:
mysql_data:
✅ 启动:
bash
mkdir -p mysql/conf mysql/init
# 放入 custom.cnf 和 init.sql
docker-compose -f docker-compose-mysql.yml up -d
六、综合性案例:LNMP 环境一键部署
L inux + N ginx + M ySQL + PHP 容器化一键部署
✅ 目录结构:
lnmp-project/
├── docker-compose.yml
├── nginx/
│ ├── Dockerfile
│ └── default.conf
├── php/
│ └── Dockerfile
└── html/
└── index.php
6.1 编写 Dockerfile
✅
nginx/Dockerfile:
dockerfile
FROM nginx:alpine
COPY default.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
✅
nginx/default.conf:
nginx
server {
listen 80;
server_name localhost;
root /var/www/html;
index index.php index.html;
location ~ \.php$ {
fastcgi_pass php:9000; # 转发到 php 服务
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
✅
php/Dockerfile:
dockerfile
FROM php:8.2-fpm-alpine
RUN docker-php-ext-install mysqli pdo pdo_mysql
WORKDIR /var/www/html
✅
html/index.php:
php
<?php
echo "<h1>Welcome to LNMP Docker!</h1>";
phpinfo();
?>
6.2 编写 docker-compose.yml
yaml
# docker-compose.yml
version: '3.8'
services:
nginx:
build: ./nginx
ports:
- "80:80"
volumes:
- ./html:/var/www/html:ro
depends_on:
- php
restart: unless-stopped
php:
build: ./php
volumes:
- ./html:/var/www/html
restart: unless-stopped
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: testdb
volumes:
- mysql_data:/var/lib/mysql
restart: unless-stopped
volumes:
mysql_data:
6.3 一键部署
bash
cd lnmp-project
docker-compose up -d --build
# 访问 http://localhost
# 应显示 PHP 信息页面
✅ 验证 PHP 连接 MySQL(修改 index.php):
php
<?php
$host = 'mysql';
$db = 'testdb';
$user = 'root';
$pass = 'secret';
$charset = 'utf8mb4';
$dsn = "mysql:host=$host;dbname=$db;charset=$charset";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
try {
$pdo = new PDO($dsn, $user, $pass, $options);
echo "<h1>🎉 LNMP 部署成功!</h1>";
echo "<p>✅ 数据库连接成功!</p>";
} catch (\PDOException $e) {
throw new \PDOException($e->getMessage(), (int)$e->getCode());
}
?>
✅ Docker/Podman 最佳实践
- 使用 .dockerignore:避免上传无用文件,加速构建
- 多阶段构建:减小镜像体积
- 非 root 用户运行:提升安全性
- 健康检查 :
HEALTHCHECK指令 - 资源限制 :
--memory,--cpus - 日志驱动 :
--log-driver=json-file --log-opt max-size=10m - 定期清理 :
docker system prune -a - 使用 Podman:生产环境推荐,更安全轻量
📚 附录:常用命令速查表
| 功能 | Docker 命令 | Podman 命令 |
|---|---|---|
| 拉取镜像 | docker pull nginx |
podman pull nginx |
| 列出镜像 | docker images |
podman images |
| 运行容器 | docker run -d --name web -p 80:80 nginx |
podman run -d --name web -p 80:80 nginx |
| 列出容器 | docker ps |
podman ps |
| 查看日志 | docker logs web |
podman logs web |
| 进入容器 | docker exec -it web /bin/bash |
podman exec -it web /bin/bash |
| 构建镜像 | docker build -t myapp . |
podman build -t myapp . |
| 启动编排 | docker-compose up -d |
podman-compose up -d |
| 清理系统 | docker system prune -a |
podman system prune -a |
🧩 综合项目扩展建议
- 部署 WordPress:Nginx + PHP + MySQL + phpMyAdmin
- 搭建私有镜像仓库 :
registry:2+ Nginx HTTPS 代理 - CI/CD 集成:Jenkins + Docker 自动构建部署
- 监控容器:cAdvisor + Prometheus + Grafana
- 容器安全扫描:Trivy / Clair 扫描镜像漏洞
- 迁移到 Podman:将现有 Docker 项目无缝迁移至 Podman
这份文档覆盖了 CentOS Stream 9 上 容器技术的全部核心知识点 + 语法细节 + 配置说明 + 实用案例 + 综合项目,所有命令和代码均含详细注释,可直接用于教学、自学或生产环境参考。