ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Docker容器化实战:从核心原理到部署排坑全指南

Docker容器化实战:从核心原理到部署排坑全指南 很多朋友第一次接触 Docker 的时候都会被“容器”这个概念搞得很迷糊。有人把它类比成轻量级虚拟机有人说它就是个进程沙箱这些说法都对但都不完整。我在实际项目里用了几年 Docker从最初的好奇折腾到后来在公司里推动整个部署流程容器化中间踩过的坑比踩过的 Bug 还多。今天这篇内容我就把对 Docker 容器学习的完整心路历程和实操经验整理出来希望能帮你跳过那些我没能绕开的坑。这篇内容适合三类朋友一是刚入门、想知道 Docker 到底是干什么用的新手二是已经会docker run但一遇到数据持久化、网络互通就抓瞎的进阶用户三是想在自己机器上部署 MySQL、Redis 等中间件、却不想把系统环境搞乱的应用开发者。我会把核心原理、安装细节、常用操作、真实部署案例以及常见故障排查一次讲透。1. Docker 到底是什么容器和虚拟机的核心区别先解决一个根本问题Docker 容器里跑的进程和宿主机上直接跑的进程到底有什么不同1.1 镜像、容器、仓库的关系用一个生活化的比喻Docker 镜像就像是一个“做菜的预制菜包”里面已经封装好了你需要的所有食材、调料和烹饪步骤甚至包括锅碗瓢盆这些依赖环境。你可以把这个菜包复制任意多份每份做出来的菜味道完全一致。而容器就是你把预制菜包拿出来“实际做出来的那道菜”的实例。仓库则是存放这些菜包的地方想吃什么口味就从中取。技术上拆开来说Docker 镜像是一个只读的模板。它包含了运行某个应用所需的全部内容操作系统的基础库、依赖包、环境变量、配置文件、启动命令等。当你运行一个镜像时Docker 会在镜像之上加一层可写层这就是容器。对容器内文件的修改、删除、新增都发生在这一层可写层上不会影响到底层镜像本体。graph LR A[镜像仓库] --|docker pull| B[本地镜像] B --|docker run| C[容器实例] C --|docker commit| D[新镜像] D --|docker push| A举个例子mysql:8.0这个镜像里包含了 MySQL 服务器程序、必要的系统库、配置模板、数据目录初始化脚本。你运行docker run mysql:8.0就是在宿主机上基于这个模板创建出一个进程实例。1.2 容器和虚拟机的本质区别很多人问Docker 容器和 VMware 虚拟机有什么区别最核心的区别在于“虚拟化的层次”。虚拟机虚拟的是硬件层每个虚拟机都需要一个完整的客户操作系统Guest OS。这意味着每启动一个虚拟机你可能要占用几 GB 内存和几十 GB 磁盘空间。而 Docker 容器虚拟的是操作系统层所有容器共享宿主机内核容器内只有应用本身及其依赖的库和二进制文件。用一个更具体的例子说明如果你在一台 8G 内存的服务器上启动 3 个虚拟机每个虚拟机分配 2G 内存可用内存就只剩 2G。但如果你在这台服务器上运行 3 个容器每个容器可能只需要几十 MB 到几百 MB 内存3 个容器合起来可能还占不到 1.5G。容器之所以能做到如此轻量关键在于它对内核名字空间Namespace和控制组Cgroup的利用名字空间隔离让容器内的进程看到的是“独立”的系统视图。每个容器拥有自己的 PID进程号、网络栈、文件系统挂载点、用户、主机名。从容器内部看它就像一个独立的操作系统但实际上只是宿主机中隔离出来的一个进程组。控制组资源限制限制一个容器能够使用的 CPU、内存、磁盘 I/O、网络带宽上限。防止单个容器把宿主机资源耗尽影响其他容器运行。注意因为容器共享宿主机内核所以容器内不能运行与宿主机内核版本不兼容的程序。比如你在一台 Windows 宿主机上没法直接运行 Linux 内核模块这也是为什么 Docker Desktop 在 Windows 上需要跑一个轻量级虚拟机默认使用 WSL2来提供 Linux 环境。1.3 为什么开发环境、测试环境、生产环境不一致的问题被解决了我团队里有一个困扰了很久的老大难问题开发说“我这边跑得好好的”测试说“我这边怎么报错”运维说“生产环境哪有时间给你调”。根本原因是三个环境之间存在差异操作系统补丁版本不同、依赖库版本不同、环境变量配置不同。引入 Docker 之后开发在代码仓库里提交一份Dockerfile或docker-compose.yml这张“配方表”定义了应用运行所需的精确环境。测试、生产都基于同一个镜像构建这一层环境差异就消失了。2. 环境搭建Windows、macOS、Linux 下的安装与踩坑在讲具体操作之前先解决“怎么把 Docker 装起来”这个实际问题。当前主流系统都有各自的安装路径但都有一些需要注意的坑。2.1 在 Windows 上安装 Docker DesktopWindows 上的 Docker 使用有两种方案老一代的 Docker Toolbox基于 Oracle VM VirtualBox已经基本淘汰现在的标准方案是 Docker Desktop它同时支持基于 Hyper-V 和基于 WSL2 两种后端。我强烈建议优先选择 WSL2 后端。相比老的 Hyper-V 方案WSL2 的启动速度更快、内存占用更少、文件访问性能也更好。在多数情况下WSL2 也是 Docker Desktop 默认预设的。安装步骤如下先在 Windows 功能中启用“适用于 Windows 的 Linux 子系统”和“虚拟机平台”。这一步可以通过管理员 PowerShell 执行dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart接着执行dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart。完成后重启系统。安装 WSL2 内核更新包。这一步容易被漏掉不更新内核的话后续启动 WSL2 可能报旧版内核相关错误。到 Docker 官网注册账号并下载 Docker Desktop for Windows 安装包。这是一个图形化的安装程序一路下一步即可。安装完成后重启系统打开 Docker Desktop等待右下角鲸鱼图标稳定表示 Docker 引擎已经启动。一个常见问题是Docker Desktop failed to start because virtualisation support wasnt detected。排查步骤也很套路先确认 BIOS 中英特尔 VT-x 或 AMD-V 虚拟化技术已开启再确认 Windows 的“虚拟机平台”功能已启用如果电脑是品牌机还要看是否在“内核隔离”相关的安全策略中把虚拟化给禁了。2.2 在 Ubuntu/Linux 服务器上安装 Docker EngineLinux 服务器的安装路径和 Windows 不同Docker Desktop 只支持个人桌面后缀。服务器推荐安装 Docker Engine# 安装基础依赖 sudo apt-get update sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common # 添加 Docker 官方 GPG 密钥 curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - # 添加 Docker 仓库 sudo add-apt-repository deb [archamd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable # 安装 Docker Engine sudo apt-get update sudo apt-get install -y docker-ce docker-ce-cli containerd.io # 启动并设置开机自启 sudo systemctl enable docker sudo systemctl start docker如果你用的是 CentOS 7Docker 20.10 版本之后就不再支持旧版docker-ce的安装流程需要把系统先升级或者沿用较老的yum install docker-ce --norestart路径。建议优先考虑升级到 CentOS Stream 或者迁移到 Rockey Linux。提示Linux 环境下安装完 Docker 后执行docker ps可能会遇到permission denied while trying to connect to the Docker daemon socket。这是因为 Docker 需要 root 权限而当前用户不在docker用户组中。执行sudo usermod -aG docker $USER后重新登录用户组权限即可务必重新登录或newgrp docker生效。2.3 镜像下载慢配置国内加速器镜像仓库默认是从海外拉取的在国内网络环境下速度通常惨不忍睹。给 Docker 配置国内镜像加速器能极大缓解这个问题。不同系统的配置路径差不多本质都是修改 Docker daemon 的配置文件即 Linux 下的/etc/docker/daemon.json或者 Docker Desktop 的 Settings Docker Engine 中配置 JSON。官方推荐的国内加速器有阿里云容器镜像服务地址、腾讯云加速器、网易云镜像等。这里以阿里云为例说明{ registry-mirrors: [https://your-code.mirror.aliyuncs.com] }需要注意每个阿里云用户分配到的加速地址不同需要登录阿里云容器镜像服务控制台在镜像仓库页面中查看专属地址。注意镜像加速器只解决拉取 Docker Hub 公开镜像的速度问题如果你要拉取私有仓库镜像加速器不生效需要通过认证或内网代理。3. 镜像与容器从拉取到运行的关键操作环境搭好了接下来是真正把“容器”跑起来。这一步会涉及几个最常用的命令也是后续一切操作的基础。3.1 拉取镜像与运行容器的完整流程以一个简单的 Nginx 为例# 1. 从 Docker Hub 拉取 Nginx 官方镜像 docker pull nginx:latest # 2. 查看本地已有的镜像 docker images # 3. 在前台运行一个 Nginx 容器并映射端口 docker run --name my-nginx -p 8080:80 -d nginx:latest # 4. 查看正在运行的容器 docker ps # 5. 访问测试 curl http://localhost:8080这一条命令里藏着好几个关键参数拆开讲--name my-nginx给容器起一个固定名字方便后续管理。如果你不指定Docker 会随机生成一个类似温柔小狗这种风格的名字。-p 8080:80宿主机端口 8080 映射到容器端口 80。容器内运行的 Nginx 默认监听 80宿主机通过 8080 访问。端口映射方向很关键别写反了。-d以后台守护模式运行让 Nginx 在后台默默服务释放你的终端。如果不加-d容器会在前台运行日志会直接打在终端上CtrlC 会关掉容器。-v挂载数据卷把宿主机目录映射到容器目录这一点后续单独展开。如果 Nginx 更新了版本你想重启后使用最新镜像需要先用docker rm -f my-nginx删除旧容器再用docker run重新创建。这不像进程那样可以直接原地升级。理解这一点对容器化思维的建立很重要容器是“宠物”还是“牲畜”容器应该是“牲畜”不配置化不手工修改容器内文件需要更新就是销毁重建。3.2 进入容器与文件传输如果需要调试容器内部# 交互方式进入容器 Bash docker exec -it my-nginx /bin/bash # 如果不确定容器里有 Bash 还是只有 sh可以先尝试 docker exec -it my-nginx sh # 拷贝文件进出容器 docker cp ./game.txt my-nginx:/usr/share/nginx/html/game.txt docker cp my-nginx:/etc/nginx/nginx.conf ./nginx.conf我实际碰到过一个场景容器内运行的镜像没有安装 Vim、没有 Bash只有精简的 BusyBox。这时候docker exec进入后交互体验极差。建议日常操作把重点放在外部文件挂载上而不是在容器内东改西改。容器一旦被删除重建内部改动就全部丢失这是容器设计的哲学。3.3 构建镜像Dockerfile 的语法与顺序问题如果你只会docker run官方镜像那只能算 Docker 的消费者。真正让 Docker 发挥价值的是自己写 Dockerfile 构建镜像。# 基础镜像 FROM python:3.11-slim # 设置工作目录 WORKDIR /app # 复制应用代码 COPY requirements.txt . RUN pip install -r requirements.txt COPY . . # 容器监听端口 EXPOSE 8000 # 启动命令 CMD [python, app.py]Dockerfile 里的每一行都会生成一个镜像层这些层是缓存的基本单位。构建顺序很重要先把变动频率低的内容如依赖声明放在前面把变动频率高的内容如应用代码放在后面。这样每次代码改动时Docker 可以复用已有层缓存构建速度会快一个数量级。以刚才的文件为例如果我把COPY . .写在了RUN pip install之前那么每一次代码修改都会导致 pip install 重新执行慢得怀疑人生。注意写 Dockerfile 时尽量把多条 RUN 命令合并成一条用连接。因为每条 RUN 都会产生一个额外的镜像层镜像层越多存储占用越大构建推送时也越慢。3.4 镜像安全与容器安全的基础意识热搜词里有“镜像安全和容器安全”这说明安全是评估容器化方案时绕不开的主题。基础的实践有两层镜像安全不要随意从第三方渠道拉取来路不明的镜像。Docker Hub 官方库中的带“官方”标记的镜像如nginx、mysql、redis通常安全性较高。非官方用户上传的镜像可能存在恶意代码因为它们本质上只是别人打包后上传到公开仓库的文件没有人强制审查。容器安全容器默认以 root 用户运行这其实是不安全的。如果一个攻击者攻破了容器进程就相当于直接拿到了宿主机 root 的部分能力。建议在 Dockerfile 中显式指定普通用户运行RUN useradd -m appuser USER appuser或者运行时指定docker run --user 1000:1000 -it my-image提示镜像是不可变的文件系统快照容器是运行态实例。即使容器出现问题也可以从同一个镜像快速启动新实例避免人工排查污染镜像内容。4. 数据持久化与网络通联实战中的两个硬骨头纯跑一个容器很容易但真实项目里数据不能丢、服务之间要通信这就要深入容器卷和容器网络的了解了。4.1 为什么容器删了数据就没了数据卷的挂载方式容器内部的文件系统是临时的容器一旦被删除容器层中的一切写入都会消失。所以 MySQL 这类需要持久化存储的中间件必须把数据挂载到宿主机目录或卷中。核心操作是-v参数或volumes配置方式一绑定挂载bind mount即宿主机目录到容器目录。docker run -d \ --name mysql-container \ -v /my/own/datadir:/var/lib/mysql \ -e MYSQL_ROOT_PASSWORDmy-secret-pw \ mysql:8.0这行命令把宿主机目录/my/own/datadir挂载到容器内的 MySQL 数据目录。宿主机上存放的就是 MySQL 真实的数据库文件哪怕容器被删除重建只要宿主机上的目录还在数据就能恢复。方式二命名卷named volume。docker volume create mysql_data docker run -d \ -v mysql_data:/var/lib/mysql \ -e MYSQL_ROOT_PASSWORDmy-secret-pw \ mysql:8.0命名卷是由 Docker 管理存储的生命周期实际文件位置在 Docker 的管理目录下你不容易直接找到原始文件但数据持久化效果和绑定挂载一致。注意绑定挂载时宿主机的目录路径要写绝对路径。写成相对路径Docker 会感觉困惑。另外宿主机目录与容器目录之间的文件权限差异也是常见坑点。如果容器内进程以 UID 999 运行宿主机挂载目录不但要是它还需要给这个 UID 开放读写权限否则会报Permission denied。4.2 使用 Docker Compose 编排多容器服务在真实项目中一个完整的业务往往由多个服务组成后端、数据库、缓存、消息队列。一个个docker run命令不高效还容易在参数上出错。这是 Docker Compose 发挥价值的场景。以部署一个带 MySQL 和 Redis 的小型 Web 应用为例version: 3.8 services: mysql: image: mysql:8.0 container_name: my-mysql environment: MYSQL_ROOT_PASSWORD: root_pass MYSQL_DATABASE: app_db MYSQL_USER: app_user MYSQL_PASSWORD: app_pass ports: - 3306:3306 volumes: - mysql_data:/var/lib/mysql networks: - app_network redis: image: redis:7-alpine container_name: my-redis ports: - 6379:6379 volumes: - redis_data:/data networks: - app_network app: build: ./app container_name: my-app depends_on: - mysql - redis ports: - 8080:8080 environment: DB_HOST: mysql REDIS_HOST: redis networks: - app_network volumes: mysql_data: redis_data: networks: app_network: driver: bridge这里教你一个关键配置DB_HOST: mysql。在同一个 Docker Compose 网络中服务可以通过服务名互相访问。应用代码里连接数据库的主机名就是mysql而不是localhost或127.0.0.1。因为容器间的网络隔离应用容器里的localhost指向的是它自己而不是 MySQL 容器。启动整个环境只要一个命令docker compose up -d查看日志、停止服务、删除服务docker compose logs -f docker compose downdocker compose down默认不会删除数据卷如果你希望连数据卷一起清理需要显式加-v。执行docker compose down -v会万劫不复把所有数据一块清掉慎用。4.3 容器网络不通先看这三层原因热搜词里“docker网络不通”出现频率很高这是新手最容易崩溃的环节。日志连连看基本上可以归为三类问题第一类是应用连接数据库失败报错类似Connection refused。这时候先检查最基础的问题docker exec进入应用容器尝试 ping MySQL 容器的服务名。如果 ping 不通说明两个容器不在同一个 Docker 网络里。解决办法是复查 Compose 配置中两个服务是否使用了同一个 networks或者用docker network connect手动把容器接入对应网络。第二类是端口映射不生效宿主机访问不到容器服务。优先检查docker ps -a中容器状态是不是 Exited异常退出或 Restarting一直重启。如果容器没起来再查容器日志docker logs my-container。如果容器在运行但访问不通确认宿主机防火墙是否放行了对应端口。第三类是不同宿主机上的容器无法互通。跨主机的容器通信需要额外配置如 overlay 网络或路由方案不是 Docker 默认安装后就能直接前置的。5. 典型场景复现用 Docker 快速部署 MySQL 8.0 与 Redis 主从说太多理论不如来一次完整的真实部署。这一部分把搜索热词里的几个高频场景连起来做一套演示。5.1 部署 MySQL 8.0 并解决中文编码问题很多朋友用 Docker 安装 MySQL之后发现写入中文会变成问号。这通常是因为 MySQL 容器的默认字符集不是 utf8mb4。docker run -d \ --name mysql8 \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORDroot_pass \ -v mysql_data:/var/lib/mysql \ mysql:8.0 \ --character-set-serverutf8mb4 \ --collation-serverutf8mb4_unicode_ci \ --default-authentication-pluginmysql_native_passwordMYSQL_ROOT_PASSWORD环境变量是初始化时指定的 root 密码。同时可以在镜像启动参数里直接附加 mysqld 的配置参数而不用专门去找配置文件挂载。用 MySQL 客户端测试docker exec -it mysql8 mysql -uroot -p在容器内执行CREATE DATABASE app_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;这样建出来的数据库就支持中文了。注意MySQL 8.0 的默认认证插件是caching_sha2_password。老版本的客户端比如 PHP 7.x 自带的 mysqlnd连接可能报认证协议不支持。如果团队里还在用老客户端需要加--default-authentication-pluginmysql_native_password或者为应用所属账号单独设置认证方式。5.2 构建 Redis 主从架构Redis 数据价值不如业务数据库高但它也是容器化的重度用户。用 Docker 搭建主从复制节点很简单# 创建 Redis 网络 docker network create redis-net # 启动主节点 docker run -d --name redis-master \ --network redis-net \ -p 6379:6379 \ redis:7-alpine \ redis-server --appendonly yes # 启动从节点 docker run -d --name redis-slave \ --network redis-net \ -p 6380:6379 \ redis:7-alpine \ redis-server --appendonly yes --replicaof redis-master 6379主从之间通过 Docker 网络内的服务名redis-master通信。务必确认从节点和主节点在同一个自定义网络中如果没有指定网络直接落到默认 bridge 网络也不是不行只要从节点能解析主节点的主机名即可实际用自定义网络管理起来更清晰。验证主从状态docker exec -it redis-master redis-cli 127.0.0.1:6379 INFO replication看到connected_slaves:1表示从节点连接成功。5.3 访问容器内的 MySQL为什么连不上这是新老手都会碰到的高频问题容器明明启动了端口映射也正常但宿主机的 MySQL 客户端就是连不上。大概率故障清单容器状态问题docker ps -a看 Exited 状态再用docker logs mysql8看有没有报错比如初始化时没给MYSQL_ROOT_PASSWORD导致这是一个问题。端口被占用宿主机上已有别的 MySQL 占用了 3306 端口容器里-p 3306:3306不能生效。换一个宿主端口比如-p 3307:3306然后客户端连接该地址和端口访问。防火墙问题宿主机的防火墙firewalld / ufw没有放行 3306 端口。环境变量问题MySQL 容器首次初始化时如果没有按要求设置MYSQL_ROOT_PASSWORD容器不会自动为 root 用户设置密码直接拒绝密码登录会报Access denied。MySQL 配置问题MySQL 8.0 默认只监听 3306 端口如果容器里改了配置成了只监听 127.0.0.1外部也连不进来。这个可以通过执行docker exec -it mysql8 mysqladmin variables | grep listen查看。5.4 用 IDEA 直接打包 Docker 镜像对 Java 开发者来说把 Spring Boot 项目打包成 Docker 镜像再用容器跑起来是容器化落地第一步。IntelliJ IDEA 的 Docker 插件可以直接完成这个操作。先安装并开启 Docker 插件Settings Plugins 搜索 Docker在 Settings Build, Execution, Deployment Docker 中配置到 Docker Desktop 的连接。如果是远程服务器配置 TCP 连接tcp://服务器IP:2375。在 IDEA 中创建一个 Dockerfile运行配置类型选择 “Docker”构建镜像时选择 Dockerfile 上下文FROM eclipse-temurin:17-jdk-alpine WORKDIR /app COPY target/*.jar app.jar EXPOSE 8080 ENTRYPOINT [java, -jar, app.jar]构建完成后在 IDEA 的 Docker 面板中可以直接右键镜像运行容器并配置端口映射。如果你不想依赖 IDE也可以直接命令行构建mvn clean package docker build -t my-demo-app . docker run -d --name my-demo-app -p 8080:8080 my-demo-app注意构建镜像的基础镜像选型会影响镜像安全性和体积。JRE 类基础镜像如eclipse-temurin:17-jdk-alpine比完整 JDK 镜像小很多。如果你用到了一些系统级工具如 curl则可以用完整基础镜像但体积会大得多。6. 常见问题排查权限、网络与镜像拉取速查表最后做一个像工具书一样的常见问题速查表把前面散落在各处的排查思路整理成清单方便你遇到问题时直接定位问题类型和排查方向。6.1 权限错误与 Docker 守护进程连接失败最典型的错误是permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock原因基本有两种。一种是当前用户不在docker用户组执行sudo usermod -aG docker $USER重新登录。另一种是 Docker 守护进程没启动Linux 下执行sudo systemctl start dockerWindows/macOS 下重新启动 Docker Desktop。如果你在 macOS 上遇到了类似错误检查 Docker Desktop 是否在系统菜单栏正常启动以及是否在 Docker Engine 高级设置中启用了 TCP socket 监听。6.2 容器一直重启Restarting 状态原因几乎都是容器内部启动命令失败退出。排查路径查看日志docker logs container_name看最后报错信息。确认启动命令本身是否正确。比如你把 Dockerfile 的 CMD 写错了路径镜像里没有这个文件容器启动就会直接退出。确认端口或存储卷是否冲突比如两个容器同时把/var/lib/mysql挂载到了同一个宿主目录。检查资源限制Docker 容器跨宿主机运行可能因为 cgroup 配置问题导致 OOM。6.3 镜像拉取速度慢或拉取失败这个问题本质上是网络受限。用镜像加速器能缓解但加速器有时也不稳定原因可能包括加速器本身服务波动、镜像体积过大等。遇到这种情况确认daemon.json配置正确后重启 Docker。用docker system prune -a清理掉不用的镜像和构建缓存给新镜像腾出空间。极个别情况下某些镜像仓库如自建 GitLab的镜像内容需要经过特殊认证此时需要先docker login registry_url。6.4 容器网络 DNS 解析失败docker run默认网络跑在 bridge 网络上容器内部通常有 DNS 解析能力。但如果配置了自定义网络并且手动设置了dns参数可能导致容器内域名解析失败。如果容器所在的网络需要访问外网比如从容器里拉取依赖包但一直没有响应尝试用docker run --dns 8.8.8.8指定外部 DNS根据实际环境调整宿主机可用的 DNS 地址例如公网 DNS 或公司内网 DNS。6.5 Docker Desktop 启动失败与 WSL2 内核问题Windows 下最常见的一个错误是Docker Desktop failed to start because virtualisation support wasnt detected这个问题不一定真的是虚拟化未开启也可能是 BIOS 被重置、Hyper-V 被禁用了。常规处理顺序重启电脑。确认「启用 Windows 功能」里「虚拟机平台」和「适用于 Linux 的 Windows 子系统」都勾选了。wsl --update更新 WSL2 内核。删除%USERPROFILE%\AppData\Local\Docker下的临时文件仅在确认安装配置无误解时操作否则可能影响配置。6.6 Windows 防火墙把 Docker 容器网络挡掉了Windows 上的 Docker 网络有个特性如果 Docker Desktop 使用的 WSL2 虚拟机的 IP 地址段和宿主机防火墙上已有一条拒绝访问规则冲突容器端口映射后外部访问可能失败。通常的处理办法是在 Windows 防火墙的入站规则中为 WSL2 虚拟网卡所在网段可以用wsl hostname -I查到放行端口或者直接关闭只是平时开发调试用防火墙对应规则中的“阻止”选项。7. 一份可以直接抄作业的后台管理命令合集前面几部分讲述的都有点“大而全”最后总结一份应急相比日常操作最为频繁、用途最广的命令清单。7.1 容器生命周期管理# 查看运行中容器含刚退出但没删的 docker ps -a # 启动已存在的容器 docker start container_id # 重启 docker restart container_id # 停止 docker stop container_id # 删除 docker rm container_id # 强制删除 docker rm -f container_id # 删除所有停止的容器 docker container prune7.2 镜像操作# 列出所有本地镜像 docker images # 删除镜像 docker rmi image_id # 删除悬空镜像 docker image prune # 查看镜像的分层结构 docker history image_id # 查看镜像细节 docker inspect image_id7.3 系统资源观察# 查看容器资源占用 docker stats # 查看容器日志并跟随输出 docker logs -f container_name # 查看容器进程列表 docker top container_name # 检查磁盘占用 docker system df经验技巧包含日志这一项Docker 容器的标准输出和错误输出都会重定向到docker logs。如果应用是 Java 技术栈日志大文件会让docker logs变得很慢这时候要么在应用层把日志写到文件再挂载到宿主要么定期用docker logs --max-size 10m --max-file 5限制 Docker 自身日志大小需要配置守护进程。8. 后续可以这样扩展你的 Docker 实战当你把单机容器用熟了以后可以尝试的方向还很多。这里根据我自己的实际经验接下来三条建议扩展方向一学习 Docker Compose 之外的容器编排工具。如果只有两三台机器用docker compose完全足够。但如果规模上去到几十台、上百台就需要学 KubernetesK8s或者 Docker Swarm。两者的核心思想都是在多个服务器之间调度容器、自动发现问题并替换实例。但 K8s 是当前行业标准学习曲线也相对陡峭。扩展方向二把 CI/CD 和 Docker 结合。容器最大的用处是给出一个可复现的构建环境。在 CI 流水线中先构建 Docker 镜像再测试再推送到镜像仓库最后在目标服务器上拉取并运行。这个流程一旦跑通版本发布就从“手工替换代码”变成了“同一个镜像在不同环境流转”。扩展方向三自己搭建镜像仓库。团队规模扩大后Docker Hub 的公共镜像仓库明显不够用可以考虑搭建 Harbor 或者用云服务商的镜像仓库。私有仓库的好处是镜像只在内网流通安全性和拉取速度都有改善镜像加速器的作用也可以相辅相成。我在实际使用中的体会是Docker 的价值远不止于“把一个应用塞进一个独立环境跑起来”。它的核心价值是让环境不再成为问题让软件交付从“代码包”变成“可运行的环境快照”。当你在本地能跑起来在测试环境能跑起来在生产环境也能跑起来很多以前一堆人吵来吵去的部署问题就会慢慢消失。最后分享一个小技巧如果你刚开始练习可以把自己常用的工具链都容器化比如 MySQL、Redis、Nginx甚至用 GitLab CI 时也可以顺手把 Runner 容器化。当你习惯容器化之后你会慢慢发现之前以为“只可能在这个机器上跑起来”的事很多时候都能换一台机器照样完美运行。这就是容器化带给你的自由度。
返回列表