资讯动态

Docker完全指南:从入门到生产部署实操

发布时间:2026/10/14 4:45:02 来源:尧图企业网站定制
很多刚开始接触 Docker 的朋友都会问一个特别实际的问题我本地跑得好好的服务怎么一部署到服务器就崩了版本对不上、缺依赖、环境变量没配全光排查这些就花掉大半天。Docker 的核心思路其实特别朴素——把应用连同它运行的整个环境一起打包像一个集装箱一样直接搬走走到哪里都原样运行。这就是镜像和容器这套机制真正要解决的问题。这篇指南不打算讲那些花哨的架构理念而是把我这几年用 Docker 的经验、踩过的坑、沉淀下来的习惯按照先懂原理再动手实操最后能排错的顺序完整梳理一遍。适合刚入门的开发者也适合已经在用但总觉得哪里不对、想系统补全知识细节的运维或后端同学。看完之后你可以独立完成从编写 Dockerfile、构建镜像到部署一套多容器应用的完整流程并且知道什么时候该用 Docker、什么时候不该用它。1. 先想明白Docker 到底解决了什么问题1.1 环境一致性噩梦与集装箱思维在容器技术普及之前应用部署的经典场景是这样的开发在本地用新版 MySQL线上还在跑老版本开发系统是 CentOS 7服务器是 Ubuntu本地依赖装得松松散散能跑线上一装就是缺这个库缺那个库。每次发布运维手里都捏一把汗开发被拉去陪跑查环境问题。这本质上是环境与代码分离造成的失真。Docker 把应用和运行环境做成了同一个交付物——镜像。镜像里包含了操作系统层、运行时、系统库、代码、配置全齐了。可以把它理解成一个大号集装箱内部怎么摆放、放了几层都在构建时定死运输过程中没人会去动里面的东西。这个集装箱标准化思维正是 Docker 解决部署一致性问题的底层逻辑。1.2 容器与虚拟机的本质区别很多人会把容器和虚拟机混为一谈。虚拟机是在宿主机上用 Hypervisor 虚拟出一整套硬件里面再跑完整操作系统资源开销大、启动慢但隔离很彻底。容器则是共享宿主机的操作系统内核通过 Namespace 做隔离用 Cgroups 限制资源本质上是一个特殊的进程集合。用一张生活化的图来描述虚拟机像租了一整套独立别墅基础设施全给你单独配好容器像住公寓水电管道共用但每家每户的门锁和隔断是独立的。容器的优势是轻量、秒级启动、磁盘占用小、密度高劣势是隔离边界不如虚拟机硬核在强安全隔离场景下虚拟机仍然不可替代。一般业务场景里容器已经完全够用而且能显著降低服务器成本。1.3 我的使用边界判断逻辑在我实际工作中遇到过有人把所有东西都塞进容器结果踩了一堆坑才回头。这里分享我的判断标准大家可以参考微服务和前后端应用容器化非常合适特别是需要横向扩容的场景。有状态数据库尤其是单机文件型数据库不是不能用但必须挂数据卷、做备份方案否则容器一删数据全没风险很高。图形化桌面环境、依赖特定硬件的任务容器方案会比较别扭不推荐硬上。纯资源密集型的批处理任务有时候直接用宿主机 crontab 反而更直接容器只做隔离反而增加了调度成本。这个边界想清楚后续的设计才不会歪。2. 环境准备与基础配置2.1 Windows、macOS 和 Linux 的安装要点在 Windows 上现在主流方案是安装 Docker Desktop它自带一个精简版 Linux 虚拟机底层是 WSL2。安装时有几个关键勾选项要注意确保开启了Use the WSL 2 based engine而且在 Windows 功能中要提前开启适用于 Linux 的 Windows 子系统和虚拟机平台。如果之前装过旧版 Docker Toolbox先彻底卸载干净否则会有莫名的端口冲突。macOS 上 Docker Desktop 的安装相对省心但有两个细节值得提第一如果电脑是 Apple Silicon 芯片M1/M2/M3尽量拉取 arm64 架构的镜像性能差别很大第二Docker 默认分配的 CPU 和内存是动态调整的建议根据自己的开发习惯手动给到 4核8G 以上不然并行跑多个容器时会明显卡顿。Linux 安装我个人的习惯是使用官方脚本先装社区版再手动启用系统服务。以 Ubuntu 系为例curl -fsSL https://get.docker.com | sh sudo systemctl enable --now docker sudo usermod -aG docker $USER第三条命令的意思是把自己的账户加入 docker 用户组之后执行 docker 命令就不需要每次加 sudo 了。加完组后一定记得退出终端重新登录一次否则组权限不会立即生效。2.2 镜像加速与版本验证在国内环境下拉取 Docker Hub 镜像经常遇到超时或者速度很慢的问题。这里不展开任何非常规手段只讲合规且常规的做法使用镜像服务提供的加速地址。在主流的容器镜像加速服务商注册后会得到一个专属加速地址配置方式是在 Docker Desktop 的设置里找到 Docker Engine 配置项或者在 Linux 下编辑/etc/docker/daemon.json{ registry-mirrors: [https://你的加速地址.example.com] }改完后重启 Docker 服务执行docker info能看到 Registry Mirrors 配置生效即可。我自己实践下来热门官方镜像基本都能明显提速但冷门第三方镜像有时加速也没用这种情况就要考虑更换基础镜像或者使用代理镜像仓库注意合规底线只选正规服务。版本验证同样不能省。执行docker version查看 Client 和 Server 两个部分都有版本号才说明 Docker 守护进程真的在正常工作。这里有个坑很多人只看到 Client 有版本就以为安装完成实际上 Server 连接失败才是常见问题尤其 WSL2 模式下跨发行版容易出幺蛾子。2.3 给新手的第一个命令hello-world 全流程装好之后我建议所有新手做的第一件事不是去网上复制一堆命令而是运行一次最简流程docker run hello-world这个命令背后发生了什么非常值得逐层理解。首先Docker 客户端会在本地查找是否存在hello-world:latest镜像如果不存在就会去 Docker Hub 拉取。拉取成功后守护进程根据镜像创建一个容器执行容器内的主程序/hello把一段欢迎文本输出到终端然后容器就正常退出了。执行docker ps时你会发现这个容器已经不在运行列表中因为它已经退出了。用docker ps -a才能看到它状态是 Exited (0)。这是一个绝佳的入门实验理解了镜像拉取、容器创建、进程运行、容器退出这四步后面所有容器操作都是在这个基础模型上展开的。3. 核心概念与命令速查3.1 镜像、容器、仓库的三角关系Docker 的三个最基础角色是镜像、容器和仓库。镜像是一个只读的模板容器是镜像运行后的实例仓库是存放镜像的远程服务器。三者的关系可以比作镜像就像安装光盘的镜像文件仓库是光盘库容器是光盘运行出来的程序进程。实际使用中我经常发现新手容易混淆镜像和容器的增删改查命令。这里给出一张对照表建议收藏操作镜像容器查看docker imagesdocker ps -a删除docker rmi 镜像名/iddocker rm 容器名/id导入导出docker save / loaddocker commit / export后续补充docker tagdocker rename特别注意docker commit可以把一个运行中的容器保存为新的镜像。虽然这是一个功能但我强烈不建议在日常开发中频繁使用它因为这种方式生成的镜像不可复现、层数混乱、体积膨胀属于应急手段。标准做法是写 Dockerfile 去构建镜像下一节会重点讲。3.2 生命周期管理的习惯性操作容器的完整生命周期包括创建、启动、停止、重启、删除。在实际操作中我很少单独使用docker create加docker start因为docker run本身就包含了这两步。但有几个命令组合值得形成肌肉记忆# 以交互方式运行并进入容器 docker run -it --rm -v $PWD:/workspace -w /workspace ubuntu:22.04 bash # 后台运行容器并且设置自动重启策略 docker run -d --restartalways --name app-server -p 8080:80 nginx:alpine # 查看容器的实时日志按时间连续输出 docker logs -f --tail 200 app-server注意上面第一个命令里的--rm它表示容器退出后自动删除临时容器。这种用法特别适合临时进入容器排查环境、做调试不会在系统里堆积一堆死掉的容器。第二个命令里的--restartalways是生产环境中非常关键的参数它能让容器在宿主机重启或进程异常退出时自动恢复强烈建议所有常驻服务都加上。-p 8080:80含义是把宿主机的 8080 端口流量转发到容器内的 80 端口。新手在这里有个常见误区容器内 80 端口是 Nginx 默认监听端口宿主机没有直接暴露 80而是映射到 8080那么访问时必须用http://服务器IP:8080而不是http://服务器IP。这个端口映射方向搞反了就会出现容器好像起来了但怎么都访问不到的困惑。3.3 数据卷删容器不丢数据的唯一解容器本身是临时的、无状态的。这是设计使然但也是很多新人跌跟头的地方在容器里直接写了数据、存了文件容器一删数据灰飞烟灭。解决方式就是数据卷Volume或绑定挂载Bind Mount。数据卷是把宿主机的一个目录挂载到容器内的指定路径容器写这个路径实际上是在写宿主机目录。我用一个最常见的 MySQL 场景来说明docker run -d \ --name mysql8 \ -e MYSQL_ROOT_PASSWORDyour_password \ -e MYSQL_DATABASEmyapp \ -p 3306:3306 \ -v mysql_data:/var/lib/mysql \ mysql:8.0这里的mysql_data是一个命名卷Docker 会自动在宿主机上创建对应的目录但位置由 Docker 管理用户不需要关心具体在哪个文件夹执行docker volume inspect mysql_data可以看到物理路径。使用命名卷的最大好处是即使将来你替换掉旧容器、升级镜像版本只要指定的卷名不变旧数据就能无缝继承到新容器的/var/lib/mysql路径下。实际工作里我一般还会给 MySQL 额外挂载一个备份目录到宿主机方便定期用 cron 做物理备份。用绑定挂载如-v /home/user/backup:/backup可以把备份结果直接落盘到宿主机熟悉的路径上而不用再进容器找文件。这是数据安全层面非常朴素的习惯但能救命。3.4 网络模式什么时候用 bridge、host、noneDocker 默认会创建一个 bridge 网络所有容器在同一个网段内可以互相通信宿主机通过端口映射访问容器。默认二字的含义是开箱即用但不代表所有场景都适合。常用网络模式可以归纳为四种bridge默认每个容器有独立 IP通过端口映射对外暴露。适合一般前后端分离项目的内部互访。host容器直接使用宿主机网络栈性能最好没有 NAT 转换开销。适合对网络延迟极其敏感、又不想做端口映射的服务但代价是应用直接占用宿主机端口失去了网络隔离。none容器没有网络只有 loopback 接口。适合离线批量任务或强调网络隔离的敏感任务。自定义 bridge 网络这是我强烈推荐的方式。它允许用容器名做 DNS 解析容器间通信无需记住 IP 地址只要写服务名就行。在多容器项目里通过自定义网络实现服务互访比用 IP 地址要稳定得多。因为每次重新创建容器 IP 都可能变而容器名不会变。具体配置方式会在后面 Compose 部分实际演示。4. Dockerfile 实战从编写到构建优化4.1 一份可运行的 Dockerfile 逐行拆解Dockerfile 是定义镜像构建过程的脚本也是 Dockr 使用中最需要基本功的部分。下面以构建一个 Python Web 服务为例给出完整可用的 Dockerfile并逐行解释关键指令的意义这段内容对应我的项目标题中完全操作指南最核心的成分之一。FROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . EXPOSE 8000 CMD [uvicorn, main:app, --host, 0.0.0.0, --port, 8000]第一行FROM决定基础镜像。我选择python:3.11-slim而非完整版 python理由是镜像体积更小、攻击面更小同时已经包含运行 Python 应用所需的绝大多数能力。如果项目强依赖 gcc 编译源码包可以临时在 RUN 阶段安装 build-essential编译完再卸载多阶段构建是另一个话题这里先不展开。WORKDIR /app指定工作目录后续的 COPY、RUN、CMD 都会在这个目录下执行。为什么不直接用默认根目录因为把项目文件放在固定目录下结构清晰也避免与系统目录文件混在一起。COPY requirements.txt .和RUN pip install ...两行放在COPY . .之前是有意安排的缓存优化。Docker 构建是按层缓存 的只要某层的内容和缓存一致就能直接复用。依赖文件不常变而项目源码经常变。把依赖安装放在前后面改代码时不会每次都重新拉 pip 包构建速度快非常多。这也是我见过很多新手的 Dockerfile 低效的常见原因把COPY . .放最前面导致任何一行业务代码的改动都触发全部依赖重新安装。EXPOSE 8000只是文档声明不产生任何实际网络行为真正暴露端口还是要靠docker run -p或者 Compose 中的 ports。这个指令更多是给镜像使用者和工具看的信息。最后CMD指定容器启动时的进程命令。有两种写法一种是这里的 JSON 数组写法推荐另一种是 shell 写法如CMD uvicorn main:app ...不推荐。因为 JSON 数组写法不会经过/bin/sh -c包装能正确接收 Docker 发的 SIGTERM 信号优雅停机。生产环境里这直接关系到服务下线时是否会残留连接、是否会丢失耗时任务。4.2 多阶段构建镜像瘦身的关键手段以 Go 或 Java 应用为例编译阶段需要完整的编译工具链体积很大运行阶段并不需要这些工具只需要最终的二进制文件或 jar 包。多阶段构建可以把编译环境和运行环境分开最终产物镜像里只有运行需要的内容。一个标准的 Go 应用 Dockerfile 示例如下FROM golang:1.22 AS builder WORKDIR /src COPY . . RUN CGO_ENABLED0 GOOSlinux go build -o /out/myapp . FROM alpine:3.20 WORKDIR /app COPY --frombuilder /out/myapp /app/myapp ENTRYPOINT [./myapp]注意两个关键点。第一AS builder给编译阶段起了名字后面的COPY --frombuilder从那个阶段的文件系统里复制文件这在实际中非常实用当你同时依赖前端构建产物时也可以用同样思路。第二CGO_ENABLED0强制纯静态编译这样产出的二进制不依赖系统的 glibc可以直接放进 alpine基于 musl libc里运行。实测同一个应用单阶段构建镜像体积可能达到 800MB 以上多阶段构建后通常能压到 50MB 以内。部署上带来的好处是质变的内网机房镜像分发秒级完成云平台拉取几乎感受不到等待。如果你从来没做过镜像瘦身这个优化是性价比最高的没有之一。4.3 构建命令与 .dockerignore 的隐性作用Dockerfile 写好后在项目根目录执行docker build -t myapp:v1.0 .最后的.表示构建上下文是当前目录。这里有个容易被忽视的细节Docker 会把整个当前目录打包发送给守护进程作为构建上下文即使是 Dockerfile 里没有用到的文件只要在目录下就会被传输。如果项目目录里有 node_modules、.git 目录、临时文件构建会奇慢无比。解法是在项目根目录创建.dockerignore文件语法与.gitignore类似但作用对象是 Docker 构建上下文.git node_modules Dockerfile docker-compose.yml *.log .env这里有个安全上的小提醒.env文件必须被排除。否则构建镜像时它会被打进镜像层将来镜像一旦被推送到公共仓库密钥就完全暴露了。这类事故在真实工作中并不罕见值得格外谨慎。5. 使用 Docker Compose 编排多容器应用5.1 为什么需要 Compose一个容器搞不定的事当项目不止一个服务时比如前端、后端、数据库、缓存、消息队列等如果每个都用docker run命令手动启动你会发现光维护启动命令就要疯掉。每次重启机器后恢复服务要按依赖顺序敲一大堆命令还容易忘记某个参数。Docker Compose 的价值在于把一组容器的定义写进一个docker-compose.yml文件里一条命令完成所有容器的创建、启动、网络互联和依赖管理。它面向的是单机多容器场景不是生产级集群编排。生产环境有更高阶的编排方案但中小型项目、测试环境、本地开发环境用 Compose 已经绰绰有余。5.2 一个真实的 Compose 文件解析下面这个文件是我比较常用的一个 Web 项目模板包含 Nginx、后端 API 和 PostgreSQL 三个服务services: nginx: image: nginx:alpine ports: - 80:80 volumes: - ./nginx.conf:/etc/nginx/nginx.conf:ro - ./static:/usr/share/nginx/html:ro depends_on: - backend backend: build: context: . dockerfile: Dockerfile environment: DB_HOST: postgres DB_PORT: 5432 DB_NAME: myapp DB_USER: myapp_user DB_PASSWORD: ${DB_PASSWORD} volumes: - .:/app ports: - 8000:8000 depends_on: postgres: condition: service_healthy postgres: image: postgres:16 environment: POSTGRES_DB: myapp POSTGRES_USER: myapp_user POSTGRES_PASSWORD: ${DB_PASSWORD} volumes: - pg_data:/var/lib/postgresql/data healthcheck: test: [CMD-SHELL, pg_isready -U myapp_user] interval: 5s timeout: 3s retries: 5 volumes: pg_data:这个文件里有几个细节值得单独拿出来讲。第一个是depends_on不再只是简单的启动顺序控制配合condition: service_healthy可以让后端真正等待数据库就绪后再启动。因为数据库容器起来了不等于数据库就能接受连接PostgreSQL 初始化需要几秒钟依赖关系写不好就会出现后端启动时连不上数据库、崩溃退出而退出的容器不会自动重试。加了 healthcheck 之后Compose 会等数据库从 healthy 状态才开始启动后端。第二个是environment中有一个${DB_PASSWORD}。这个变量从宿主机环境变量里读取做法是在.env文件里定义实际值敏感内容不直接写进 yaml 文件。这是防止密钥泄露的底线操作。第三个是 Nginx 那里的挂载带了:ro后缀只读挂载。配置文件和数据文件在容器里不需要被修改全部设为只读既安全又少了一层被误改的危险。5.3 Compose 常用命令与升级策略日常使用 Compose我的核心命令集其实就是这几个# 构建并后台启动 docker compose up -d --build # 查看各服务状态 docker compose ps # 查看聚合日志 docker compose logs -f # 停止服务但不删除数据卷 docker compose down # 完全清理包含数据卷慎用 docker compose down -v特别提醒down -v这条命令会连带删除所有数据卷彻底销毁数据库数据。我见过不止一次本来只是想停一下服务结果因为习惯性加-v把库给清了。建议在数据库相关项目里不要加-v或者配置文件做二次确认。升级项目代码后重启服务的正确姿势是先docker compose build构建新镜像再docker compose up -d重建变更的容器。Compose 会比较镜像变化只重建需要的服务其余保持运行整体发布成本非常低。6. 十个高频问题与排查思路6.1 容器启动了但访问不了排查路径这个问题是新手咨询率最高的。按我的经验按顺序排查可以覆盖 90% 以上的情况第一确认容器确实在运行。docker ps没有输出就说明容器已经退出继续用docker logs 容器名看退出原因。第二确认端口映射是否正确。docker port 容器名可以看到实际映射关系如果输出为空说明创建时没有指定-p参数自然无法从宿主机访问。第三确认防火墙放行。云服务器安全组、宿主机 iptables任何一个拦截了宿主机端口都会导致容器内正常但外网不通。第四确认容器内监听地址是否绑定了 0.0.0.0。有些应用默认绑 127.0.0.1只允许本机访问容器外部就完全连不上。6.2 镜像拉取超时的底层原因与绕行思路镜像拉取失败的报错文本通常包含Timeout exceeded while awaiting headers或dial tcp: lookup ... no such host。第一个场景往往是网络到镜像仓库的链路问题配置镜像加速是首选方案第二个场景通常是无 DNS 解析宿主机 DNS 配置有问题检查/etc/resolv.conf或公司网络出口。还有一个少有人想到的排查点镜像仓库偶尔会出现损坏的 manifest 索引导致拉取中间卡住。这时候可以试试补拉特定 tag 而不是 latest或者到仓库网页端确认该 tag 是否存在。如果某镜像反复拉不下来建议换一个功能等价的基础镜像不要死磕。6.3 容器时间不对与日志不滚动Docker 容器默认使用 UTC 时区宿主机如果设置了 Asia/Shanghai容器内依然显示 UTC 时间。应用日志时间与我本地时间相差 8 小时排查线上问题时很容易误导判断。根治方法是在 Dockerfile 里预先设置时区RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime ENV TZAsia/Shanghai注意ln -sf会覆盖原有的/etc/localtime软链不会破坏系统文件。如果是在用别人的现成镜像不方便改 Dockerfile可以在docker run时加-e TZAsia/Shanghai和-v /etc/timezone:/etc/timezone:ro实测也能解决绝大多数应用的时间问题。日志不滚动的问题同样常见。容器内应用日志如果直接写文件而不打印到 stdoutDocker 的日志驱动并不会收集它而文件会无限增长撑满磁盘。建议所有容器内的进程都尽量把日志写到标准输出宿主机用docker logs统一查看。实在有特殊需求必须写文件也要在容器内部配置 logrotate或者把日志挂载出来交给宿主机清理机制处理。6.4 容器退出码的含义速查容器退出后执行docker inspect可以查看退出码不同码的含义差异很大0正常退出进程自己结束通常不是错误。1一般错误应用启动失败或运行中异常退出。看日志排查。2通常是 shell 内置命令语法错误或者环境变量未定义导致的。126/127权限问题或命令不存在。常见于 Dockerfile 里 CMD 写错路径或者容器内没有对应可执行文件。137进程被 SIGKILL 杀掉。常因为 OOM内存超限查看docker inspect里的OOMKilled字段是否为 true。每次容器退出我第一反应不会是去反复重启而是先docker logs看应用自身报错再docker inspect看资源限制和退出码背景。这两步基本能定位 80% 的问题。6.5 磁盘被 Docker 占满的清理方案Docker 是磁盘空间消耗大户镜像层、容器读写层、悬空镜像、日志文件都会慢慢侵蚀宿主机磁盘。常用排查命令组合是docker system df它会列出镜像、容器、本地卷、构建缓存各自占用的空间。清理三板斧按安全程度依次执行# 一级清理悬挂镜像没有 tag 的旧镜像层和停止的容器 docker system prune # 二级加 -a 连没有使用的镜像也清掉 docker system prune -a # 三级连带卷清理只建议确实数据都不要了时执行 docker system prune -a --volumes每次构建新镜像都会残留大量旧的悬空镜像层日常开发建议每周执行一次第一层级清理。生产环境清理前一定先确认没有在用低版本镜像回滚的需求否则要保留几个最近版本的镜像再清。7. 生产环境落地时的安全与性能基线7.1 容器内非 root 运行的必要性镜像默认以 root 身份跑进程是生产环境一个非常大的安全隐患。一旦容器被攻破攻击者就拥有了宿主机上 root 级别的操作路径尤其是配合一些权限配置不当的情况后果会非常严重。最直接的缓解措施是在 Dockerfile 里创建一个非特权用户并切换过去RUN groupadd -r app useradd -r -g app app USER app注意USER指令要放在所有需要 root 权限的操作之后比如安装依赖、修改文件权限之后的所有 RUN/CMD/ENTRYPOINT 都会以这个用户身份执行。如果应用需要写数据卷确保该目录对 app 用户可写。否则启动后会发现应用疯狂报 permission denied。7.2 资源限制防止一个容器拖垮整台机器不限制资源的容器理论上可以耗尽宿主机的所有 CPU 和内存尤其是有内存泄漏问题或其他失控进程时。Docker 提供了轻量级的限制参数我建议所有常驻容器都必须设置docker run -d \ --memory 512m \ --memory-swap 512m \ --cpus 0.5 \ --pids-limit 100 \ myapp:latest--memory限制内存上限--memory-swap设置为与内存一致等于禁用了 swap这个组合能有效防止容器因 swap 变卡。--cpus限制 CPU 使用额度0.5 表示最多使用半个核心。--pids-limit限制容器内可创建的进程数能防 fork 炸弹一类的应用失控。实际项目里内存限制给得太紧会导致业务高峰期被 OOM 杀死给得太松就失去了限制意义。我的习惯是先不限制跑一周用docker stats观察峰值再按峰值留出 20% 到 30% 余量去设置。7.3 镜像签名与供应链安全公共仓库拉镜像很方便但依赖链上的安全问题很现实。镜像里被塞挖矿程序、被投毒的例子并不罕见生产安全要求高的团队一定要有供应链安全意识。实际落地时能做的基础工作包括只从信誉良好的官方来源拉基础镜像不随便使用来路不明的第三方镜像固定镜像 tag 的完整摘要digest而不是使用会漂移的 latest定期扫描镜像漏洞使用 Trivy 这类工具配合 CI 做自动化。这些措施组合起来能极大降低镜像层被植入恶意代码的风险。8. 最后说几句实际经验用 Docker 这几年我最大的感受是容器化真正解决的不仅是部署问题它改变了团队协作的方式。过去是你把你本地环境截图发过来我来看看吧现在是我们都跑同一个镜像出问题的方式就是拉一下最新镜像。这种消除环境差异带来的信任感是容器技术最容易被低估的价值。如果你正在从零开始学 Docker我不建议把官方文档从头翻到尾。更实际的路径是拿手头一个真实的小项目先写一个能用 Dockerfile 跑起来的容器再一步步加入数据卷、多服务编排、健康检查每加一层都会遇到问题解决问题的过程才是真正学会的过程。Docker 的命令并不复杂复杂的是在真实场景中权衡取舍的能力这些只能靠实操积累。最后再分享一个很多人忽略的小习惯在任何生产环境的操作之前先执行docker system prune -a会把不在使用的镜像全清掉万一旧镜像有回滚需求就麻烦了。正确的做法是把回滚和清理这两个目标分开保留最近稳定版本后再做清理。这一个看似微小的操作习惯就能避免大部分清完环境发现没法回滚的尴尬。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑