恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

Docker入门实战:从容器基础到部署全解析

  • 首页
  • 资讯中心
  • /
  • Docker入门实战:从容器基础到部署全解析

相关资讯

科研工作记录怎么写?从流水账到可复现过程资产的完整模板 2026/10/20 17:21:56
海信UX2026款旗舰电视深度解析:Mini LED画质与技术全解读 2026/10/20 17:16:56
如果PHP网站访问慢,你怎么判断是交换机、路由器还是服务器的问题? 2026/10/20 17:16:56

最新资讯

AI在建筑行业落地全解析:从生成式设计到施工管理
AI原理选择题的工程化复用:从备考资料到知识图谱与插件开发
机器人ESD整改避坑指南:从机理定位到接地屏蔽的工程实践
AI安全红队实战:从提示注入打穿到数据库层的完整演练
AI任务闭环设计:用流程化工作流让Codex从散装自动化走向稳定产出
开源Agent框架源码拆解:插件化如何成为架构骨架

今日推荐

高频变压器实战经验总结:磁芯选型、绕组工艺与故障排查全解析
U-Boot移植的关键:深入理解Kconfig配置系统与依赖关系
步进电机原理与调试全解析:从步距角到丢步排查

本周热门

基于GMM的语音识别系统原理与MATLAB实现详解
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

本月精选

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证
2026 大模型集体涨价:用 Python 做企业 Token 成本测算与选型避坑(附配置)

Docker入门实战:从容器基础到部署全解析

发布时间:2026/10/20 17:21:56
Docker入门实战:从容器基础到部署全解析 直接开始写。1. 为什么要学 Docker先搞清楚它解决什么问题我最早接触 Docker 是在一次代码上线事故之后。某个项目在本地跑得风生水起代码一提交测试同事那边直接起不来。查了半天人家环境里缺了个系统库版本也不对。这种问题相信每个人都经历过背后就是那个老生常谈的“环境不一致”问题。Docker 的本质其实就是把你的应用和它运行所需要的环境打包到一起。这个环境包括操作系统依赖、运行时、系统库、配置文件、环境变量全部装进一个标准化的“盒子”里。这个盒子在任何装了 Docker 的机器上跑到哪里都是一毛一样的行为。这就是它的核心价值一次构建到处运行。1.1 环境不一致的痛点先聊聊环境问题背后的真实场景。我们开发的时候用的是自己的电脑可能是 Mac可能装了一堆配置代码提交之后测试环境是 Linux而且测试服务器上可能已经跑了好几个项目依赖互相污染。前端还好一点后端涉及的系统库、Python 或 Node 版本、环境变量哪一个不对都跑不起来。我记得做一个数据清洗任务的时候本地用的是新版 JSON 解析库测试机上旧版本的库不兼容结果代码跑一半直接崩了。排查了大半天就是环境版本问题。如果没有 Docker这类问题几乎无解总不能每次部署都手动去配环境。而 Docker 的思路是你把项目用到的所有依赖装进镜像别人拿到镜像直接运行根本不用关心底层是什么系统、缺什么库。1.2 Docker 的核心价值除了环境一致性Docker 还有两个非常实际的好处。第一是资源隔离。一个容器就像一台轻量级的虚拟机但它不像虚拟机那样需要模拟整个硬件而是直接和宿主机共享内核所以启动速度极快资源占用也低。同一台服务器上你可以同时跑几个完全不同的应用它们互不干扰。某一个容器挂掉了不影响其他容器。第二是快速部署和弹性伸缩。以前上线一个新项目要装环境、配依赖、启动服务少说几个小时。现在镜像打好了几秒钟就能拉起一个一样的容器实例。流量大的时候同一台机器上多跑几个容器就是扩容用完就删。这种弹性的便利性在没有容器技术之前是完全不可想象的。提示很多初学者会把 Docker 当作虚拟机的一个替代品但实际上它们的定位不同。虚拟机虚拟的是硬件层而 Docker 虚拟的是操作系统用户态。不懂底层原理可以先跑起来后面自然会理解。这个系列我会一步步带着你从零开始把概念、原理、命令、实战全部过一遍。这一篇先解决认知和基础环境的问题。2. Docker 的三个核心概念镜像、容器、仓库上手之前有三个概念必须先理清楚。镜像、容器、仓库这三者的关系可以拿编程里的“类、实例、代码库”来类比。2.1 镜像打包好的模板镜像是 Docker 的核心它是一个只读的模板里面包含了你运行一个应用需要的全部文件。你可以理解成一台电脑的“系统安装盘”里面已经装好了操作系统、驱动、软件拿过来直接安装就能用。镜像是分层存储的这一点很重要。构建一个新的镜像时每一行指令都会生成一个只读图层。多个镜像可以共享相同的底层图层比如所有基于某个基础镜像构建的应用都会复用同一个基础层。这样做的好处是节省磁盘空间拉取镜像的时候如果底层已经存在只需要下载增量部分。拿实际项目举例你要部署一个 Python Web 应用镜像里会包含一个操作系统发行版比如精简版 Linux、Python 运行时、你的代码、以及用到的第三方库。别人拿到这个镜像不需要安装 Python也不需要装依赖直接就能运行。2.2 容器运行中的实例容器是镜像运行时的实例。镜像是只读文件容器则是在镜像之上加了一层可写层。你启动一个镜像Docker 就会在镜像的只读层上创建一个可写层这就是容器。打个比方镜像是做蛋糕的模具容器是用这个模具做出来的一个个蛋糕。同一个模具可以做无数个蛋糕同一个镜像也可以启动多个容器。每个容器之间是相互隔离的有自己的文件系统、网络、进程空间。容器的启动速度非常快因为本质上是宿主机上的一个进程只是利用内核的命名空间和 Cgroups 机制做了资源隔离。容器里的数据是易失的。一旦容器删除容器里新增的所有数据都没了。所以真正的数据要挂载到宿主机或者使用数据卷来持久化这个后面会单独讲。2.3 仓库存放镜像的地方仓库是集中存储和分发镜像的服务器。最常用的公共仓库是 Docker Hub你拉取的大部分官方镜像都来自那里比如官方的基础镜像、常用的数据库和服务镜像。仓库的命名规则需要注意一下完整格式一般是“命名空间/仓库名:标签”。比如nginx:1.25nginx是仓库名1.25是标签代表具体的版本。如果不写标签默认拉取latest最新版本。在企业里你可能会搭建私有的镜像仓库用来存放自己构建的镜像供团队内部使用。注意事项生产环境中强烈不建议使用latest标签。原因很简单今天拉下来的latest和三个月后拉下来的latest可能是完全不同的版本一旦上游更新了导致不兼容你根本说不清楚问题出在哪里。给镜像打上明确的版本号是规范化运维的第一步。这三个概念是 Docker 的基石。看着简单但是后面所有的操作都离不开它们。理解不深没关系先把这里记下来实际操作中你会慢慢建立起直观的感觉。3. 从安装到第一个容器环境准备在你本地把 Docker 跑起来这是系列一最核心的目标。我用的是最常见的方式直接安装 Docker 桌面版因为对新手最友好自带图形界面和管理面板能帮你直观地看到容器状态。3.1 安装 Docker 桌面版Docker 的安装在不同操作系统上略有差异。我以 Linux 和桌面系统分别来说。如果你用的是 Windows 或 macOS直接下载安装包一路默认设置安装即可。安装完成后可能需要重启或者退出登录让 Docker 的系统代理和权限生效。Windows 下要确保开启了硬件虚拟化macOS 下要求在较新的系统版本上运行。如果你用的是 Linux以 Ubuntu 为例可以用官方脚本一键安装也可以手动添加软件源来安装。我倾向于手动安装因为可控性更强# 更新软件源 sudo apt update sudo apt install -y apt-transport-https ca-certificates curl software-properties-common # 添加 Docker 官方 GPG 密钥和软件源 curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg echo deb [archamd64 signed-by/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable | sudo tee /etc/apt/sources.list.d/docker.list /dev/null # 安装 sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io # 启动并设置开机自启 sudo systemctl enable docker sudo systemctl start docker安装完成后用docker --version验证一下。如果能看到版本号说明装好了。3.2 配置镜像加速器这一步在很多网络环境下其实是刚需可以不加但加了之后能明显提升拉取镜像的速度。Docker 默认从 Docker Hub 拉镜像在某些地区速度不稳定。配置一个镜像加速服务Docker 会从加速地址拉取速度快很多。在 Docker 桌面版里打开设置找到 Docker Engine 配置项在 JSON 配置里加上注册服务地址{ registry-mirrors: [ https://docker.mirrors.ustc.edu.cn ] }不同服务商的加速地址不一样你自己找可用的即可。配置完保存重启 Docker用docker info能看到 Registry Mirrors 那一栏列出了你配置的地址。提示镜像加速器只对拉取公开镜像有效如果涉及私有镜像还是要走正常的认证流程。3.3 运行第一个容器环境就绪之后我们做一个所有 Docker 初学者都会做的实验运行一个 hello-world 容器。docker run hello-world这条命令的执行过程是这样的首先 Docker 会在本地查找有没有hello-world这个镜像如果没有它会自动从配置的仓库拉取。拉取完成之后Docker 根据镜像创建并启动一个容器容器执行完镜像里预设的命令输出一段欢迎信息然后退出。看到类似Hello from Docker!的输出就说明你的 Docker 环境完全正常了。接着我们再跑一个稍微有点实际意义的容器比如一个 nginxdocker run -d -p 8080:80 --name my-nginx nginx:1.25解释一下这几个参数-d后台运行容器-p 8080:80宿主机 8080 端口映射到容器内 80 端口--name my-nginx给容器起一个名字方便管理nginx:1.25镜像名加明确的版本号执行完以后打开浏览器访问http://localhost:8080如果你能看到 nginx 的欢迎页面第一个容器就正式跑起来了。4. 镜像管理拉取、查看与删除容器跑起来了接下来进入日常使用频率最高的部分镜像管理。很多人学 Docker 学了半天命令背了一堆其实真正每天用到的就那么几条。这里我把最实用、最高频的镜像操作全部过一遍。4.1 拉取镜像时该注意什么拉取镜像是docker pull但我在实际使用中总结出了几个小技巧新手很容易踩坑。第一个是不写标签会默认拉latest。很多教程里直接写docker pull nginx看起来很方便但如果你指望“最新版”适合生产使用那就大错特错了。官方发布latest标签往往是跟随最新的主版本这个版本可能是稳定版也可能是刚发布的新版本停留在不同的语义化版本上。版本之间的配置差别很可能让你的部署脚本失效。所以要养成写标签的习惯。第二个是注意镜像的大小。同样是 nginx默认镜像体积在 190MB 左右但如果拉取精简版nginx:alpine体积能缩小到 40MB 左右。alpine是一个极简 Linux 发行版体积小安全性相对更好因为攻击面小。很多镜像都提供了 alpine 变体适合那些不需要复杂调试工具的场景。第三个是官方镜像和社区镜像的辨识。在仓库中不带命名空间的通常是官方镜像例如nginx、redis、ubuntu。带命名空间的通常属于个人或组织发布比如bitnami/nginx这种。社区镜像的质量参差不齐使用前最好确认一下它的维护活跃度和下载量。4.2 查看和删除镜像查看本地镜像很简单docker images这个命令会列出镜像仓库名、标签、镜像 ID、创建时间和大小。注意镜像 ID 是一个 64 位的十六进制字符串通常只需要用前 4 位以上的字符就能唯一标识比如你看到docker images显示abc123456789后面操作时只需要写abc1就够了Docker 能识别。删除镜像用docker rmidocker rmi image_id如果镜像正被一个容器使用删除会报错。你需要先删除依赖它的容器或者加-f强制删除。我不建议频繁使用-f因为这样可能留下一些孤儿资源虽然功能上没问题但需要你去手动清理操作多了会觉得麻烦。批量清理没用的悬空镜像可以用docker image prune这个命令会删除所有“没有被任何容器引用”且“没有打标签”的镜像层。注意它不会删除正在使用的镜像所以可以放心执行。4.3 镜像的导入导出有些场景下你需要把镜像从一台机器迁移到另一台机器尤其是离线环境。这种情况下可以用docker save -o my-image.tar my-image:tag docker load -i my-image.tarsave导出的是镜像的完整 tar 包load把 tar 包加载进来。另外一个容易混淆的是export和import它们操作的是容器的文件系统不是镜像本身。容器 export 出来的文件系统import 进去就不再是一个标准的镜像丢失了层信息和构建历史所以容器导入导出的方式很少用于镜像迁移。经验分享生产环境做镜像迁移永远用save/load组合不要用export/import。后者会丢失镜像的元数据和历史层导致后续无法基于原镜像做增量更新。5. 容器管理启动、停止、进入与日志镜像管理熟练之后真正的重头戏是容器操作。我把这套流程从创建到销毁的完整生命周期讲清楚。5.1 容器的创建与启动创建容器有一条必学的命令docker run。它把“创建容器”和“启动容器”两个步骤合在一起完成了。最基础的写法docker run --name my-ubuntu -it ubuntu:22.04 /bin/bash-it是-i和-t的组合-i表示保持标准输入打开-t分配一个伪终端。这条命令会创建一个 Ubuntu 容器然后以交互模式进入容器的 bash shell。在容器里敲命令跟在一台虚拟机里操作的感觉很像。如果你需要在容器创建时不进入交互模式而是让它在后台静静运行那就是之前用过的-d。加不加-d取决于这个容器是不是一个常驻服务。数据库、Web 服务这类容器通常用-d后台运行调试类、一次性任务类的容器通常用-it交互运行。容器停止之后如果不删除它依然存在于磁盘上。你随时可以用docker start my-ubuntu重新启动这个“已存在但停止”的容器而不是重新创建一个新的。这样做的好处是你上次往容器写的数据还在。5.2 进入运行中的容器很多时候容器在后台跑着你需要进去查看环境、调试排错。这里有几种方式。方式一使用docker execdocker exec -it my-ubuntu /bin/bash这条命令在目标容器里启动一个新进程并把当前终端接入这个进程的标准输入输出。这是生产环境里最常用的调试方式。方式二使用docker attachdocker attach my-ubuntuattach直接连接到容器的主进程。区别在于exec是“额外开了一个进程”进入容器attach是“把自己附着在容器的 PID 1 上”。如果你用attach一旦你从终端退出就有可能同时把容器的主进程杀掉这在生产环境是很危险的。所以我的习惯是只进里面执行命令永远不会用attach。警告不要在运行中的生产容器里用attach去“看一眼”你的 CtrlC 或 CtrlD 操作很可能导致主进程收到中断信号直接终止整个容器服务。5.3 日志Debug 的第一手资料拿到一个容器我先做的事永远是看日志。docker logs my-nginx这个命令会把容器主进程的 stdout 和 stderr 输出全部打印出来。加上-f可以持续跟踪最新输出类似tail -fdocker logs -f --tail 100 my-nginx--tail 100表示只显示最近 100 行这个参数在日志非常多的场景下特别有用。如果你发现一个容器启动后马上退出了那就去看日志基本能定位九成的问题。5.4 容器的删除与清理删除单个容器docker rm my-ubuntu删除所有已停止的容器docker container prune我建议每隔一段时间跑一次这个清理命令。开发调试过程中会遗留大量的停止容器占着磁盘空间还容易让人分不清哪些是真正在用的。强制删除正在运行的容器用docker rm -f。它会向容器主进程发送 SIGKILL 信号直接终止它。能少用就少用尽量先docker stop让它优雅退出再做删除。优雅退出会给应用一个处理善后工作的机会比如保存状态、关闭数据库连接、释放资源。6. 端口映射与数据持久化让容器真正可用容器本身跑起来只是一个隔离环境要被外部访问、要持久保存数据就必须处理端口和存储的问题。6.1 端口映射的两种姿势容器内部跑着一个服务默认情况下外部网络是访问不到的。刚才我们用-p 8080:80做了端口映射把宿主机的 8080 端口转发到容器的 80 端口。这个映射方式有一个明显的问题宿主机 8080 的端口被占用了就没法再起第二个容器映射同一个端口。如果你要部署多个 nginx 实例就得手动指定不同的宿主机端口。我在本机调试时经常把端口改成随机的避免冲突。另一种方式是-P大写字母 P它会自动为容器内部所有暴露出来的端口分配一个随机的高位端口。执行docker ps就能看到端口映射情况。这种方式适合快速测试但不适合长期稳定的服务。端口映射的生效时机是在创建容器时端口映射一旦设定之后修改不了。所以你如果需要改映射只能删除容器重新创建。这一点不少新手会踩坑在容器里面把服务端口改了以为宿主机上的映射端口也会跟着变其实不会。6.2 数据持久化数据卷与绑定挂载默认情况下容器内文件系统在容器删除后会被清空。数据的持久化靠的是数据卷和绑定挂载。数据卷是 Docker 管理的特殊目录它的生命周期不受容器生命周期约束docker run -d --name mysql-server -v mysql-data:/var/lib/mysql mysql:8.0这里-v mysql-data:/var/lib/mysql把名为mysql-data的卷挂载到容器的 MySQL 数据目录。你删除容器卷还在数据不会丢。下次新建容器挂载同名卷数据就自动回来了。查看卷列表docker volume ls绑定挂载更直白直接把宿主机的某个目录挂到容器里docker run -d --name web-nginx -v /home/user/html:/usr/share/nginx/html nginx:1.25修改宿主机/home/user/html里的文件容器内的 nginx 网站内容会立即更新。这在开发调试时特别方便改代码不用重新构建镜像。关于数据管理有一条铁律数据库的数据目录和数据卷必须挂载到宿主机。放任数据库数据存在容器可写层内容器一删整个库的数据就消失了。6.3 容器间的通信容器之间需要相互访问时用 IP 去访问是不靠谱的因为容器的 IP 在重启后会变化。正确的方式是创建自定义网络docker network create my-net docker run -d --name mysql-server --network my-net mysql:8.0 docker run -d --name backend --network my-net my-app-image:latest在同一个自定义网络里的容器可以直接通过容器名进行 DNS 解析。比如在backend容器里数据库的连接地址直接写mysql-server:3306就行而不用去关心 MySQL 容器的实际 IP。这是多容器应用部署的基础。上一篇暂时用不到但你要有这个认知容器编排的核心就是通过 Docker 自定义网络实现服务发现。7. 常用命令速查与排查技巧到最后我把这几天的实操经验浓缩成一张常用的命令表以及几个最常见的报错场景。7.1 高频命令速查表用途命令示例说明拉取镜像docker pull nginx:1.25指定 tag 拉取查看镜像列表docker images展示本地所有镜像删除镜像docker rmi image_id删除未被容器引用的镜像创建并启动容器docker run -d -p 8080:80 nginx:1.25后台运行并做端口映射列出运行中容器docker ps-a 可查看已停止的容器停止容器docker stop my-nginx优雅停止发送 SIGTERM强制停止容器docker kill my-nginx直接发 SIGKILL删除容器docker rm my-nginx删除已停止的容器进入容器docker exec -it my-nginx /bin/bash在容器内启动 shell查看日志docker logs -f --tail 100 my-nginx跟踪最新日志查看资源占用docker stats实时显示 CPU/内存/网络查看容器配置与网络docker inspect my-nginx输出 JSON 格式的详情清理全部未使用资源docker system prune -a慎用会清掉很多镜像docker stats是我特别推荐你上手立刻试一下的命令。它能实时看到每个容器的 CPU 占用、内存占用、网络 IO排查资源瓶颈的第一利器。7.2 报错排查思路这一块用实战经验说话。下面是初学者最多遇到的三个问题的排查思路。第一个是Failed to connect to the Docker daemon。出现这个错误说明你的客户端连不上 Docker 引擎。桌面版需要确认是否正常启动Linux 下需要确认 docker 服务是否在运行执行systemctl status docker查看。如果没问题再看当前用户有没有加入 docker 用户组。没加的话每次都要用 sudo否则就会报这个错。第二个是port is already allocated。端口被占用说明宿主机上这个端口已经被某个容器占了。用docker ps看看谁占着要么停止那个容器要么换一个宿主机端口。第三个是No space left on device。这是容器日志或镜像堆积导致的磁盘溢满。先执行docker system df查看磁盘使用情况然后清理不再需要的容器和镜像。如果是特定容器日志太大可以通过给 Docker 配置日志轮转去解决而不是手动删除日志文件因为容器还在写着这个文件。7.3 容器日志体积过大很多人遇到磁盘满了第一反应是清理镜像忽略了日志。一个长期不重启、日志量很大的容器几天就能产生几个 GB 的日志文件。解决办法是在启动容器时限制日志文件大小docker run -d --log-opt max-size10m --log-opt max-file3 nginx:1.25这样每个日志文件最多 10MB最多保留 3 份循环覆盖。生产环境建议所有容器都加上这个配置成本低收益显著。7.4 一个常识性建议分清容器和镜像的命名规范容器和仓库/镜像的命名规则有一定区别。容器名可以随便取但只能用字母、数字、下划线、点号和连字符镜像的完整标识是“仓库名:标签”。刚开始学的时候容易把容器名和镜像名混在一起比如运行docker rm nginx:1.25然后就会得到invalid reference的错误。记住容器操作用的是容器 ID 或容器名镜像操作用的是镜像 ID 或镜像名两者不要混用。8. 构建自己的第一个镜像用 Dockerfile 从零开始系列的最后一篇我们来做一个“真正属于自己的”镜像。前面你一直在拉别人的镜像现在开始亲手写一个 Dockerfile。8.1 结构解析Dockerfile 是一个包含了一系列指令的文本文件Docker 会按照文件里的指令一步一步构建出镜像。举一个最简单的 Python 应用示例# 指定基础镜像 FROM python:3.11-slim # 设置工作目录 WORKDIR /app # 把本地的 requirements.txt 复制进镜像 COPY requirements.txt . # 安装依赖 RUN pip install --no-cache-dir -r requirements.txt # 把当前目录的代码复制进镜像 COPY . . # 声明容器运行时监听的端口 EXPOSE 8000 # 容器启动时执行的命令 CMD [python, app.py]这段代码涵盖了几个最核心的指令FROM一切的基础必须放在第一行。你的镜像基于哪个镜像构建。WORKDIR后续指令的工作目录。不设置的话默认在根目录文件存放会乱。COPY把宿主机上的文件复制到镜像里。上面把requirements.txt复制过去是为了在安装依赖时能用到它。RUN在镜像构建过程中执行的命令。不推荐在 README 里写的命令行里装依赖而是用RUN固化进镜像。EXPOSE声明这个镜像里服务要用的端口。注意它只是声明并不能真正让宿主机访问到还是要配合-p来实现端口映射。CMD容器启动时执行的默认命令。一个 Dockerfile 只能有一个CMD生效多个的话只有最后一个生效。8.2 构建镜像准备好 Dockerfile 和项目代码后在项目根目录执行docker build -t my-python-app:v0.1 .最后这个.是构建上下文Docker 会把当前目录的文件打包发给构建进程。所以构建期间目录里大文件、敏感文件要特别注意尽量放在.dockerignore文件里就像 Git 的.gitignore一样__pycache__ *.pyc .env .git构建过程会逐行执行 Dockerfile 的指令每一步生成一层镜像图层。如果某一步出错Docker 会给出错误提示。构建完成运行它docker run -d -p 8000:8000 --name my-python-app my-python-app:v0.18.3 关于镜像层缓存的实践心得Docker 构建过程中有层缓存机制。如果某个指令没有发生变化Docker 会直接使用缓存层不重新执行。利用好这一特性能大幅缩短构建时间。拿上面的 Dockerfile 来说我把COPY requirements.txt放到COPY . .前面就是典型的缓存优化。因为requirements.txt很少变动安装依赖的层可以长期命中缓存只有当你改了依赖时才会重新安装依赖。如果把代码先复制进去那么每次代码变动安装依赖的步骤都会因为代码发生变化而失效整个构建过程就非常慢。注意事项写 Dockerfile 时指令顺序会影响构建效率乃至影响镜像的复用率。把“频率低变动”的步骤放前面“频繁变化”的步骤放后面是 Dockerfile 优化的核心原则。8.4 多阶段构建的概念如果你构建一个编译型应用的镜像比如 Go 或者 Java镜像里会多出很多编译工具和临时文件体积非常大。多阶段构建可以用一个临时镜像完成编译最后只把编译产物复制到最终镜像# 阶段一编译 FROM golang:1.22 AS builder WORKDIR /app COPY . . RUN go build -o my-app # 阶段二只拷贝产物 FROM alpine:latest WORKDIR /app COPY --frombuilder /app/my-app . CMD [./my-app]最终生成的镜像只包含一个精简的操作系统和一个二进制文件体积从几百 MB 降到几十 MB。生产环境部署这种镜像不仅拉取快安全风险也低。9. 常见问题与避坑实录这一路写下来我发现学 Docker 的阻碍往往不是命令本身而是那些“没被说明书写清楚”的坑。这里集中整理一下我在实践中遇到频率最高的问题和处理方案。现象原因解决办法Got permission denied while trying to connect to the Docker daemon当前用户不在 docker 用户组sudo usermod -aG docker $USER重新登录容器启动后立即退出前端进程没保持容器没有任务可执行让进程在前台运行例如写CMD [nginx, -g, daemon off;]或tail -f /dev/nullport is already allocated宿主机端口已被占用换端口或停掉占用端口的容器容器内时间不对时区默认 UTC挂载宿主机时区文件或设置TZ环境变量容器内文件权限不对容器用户非宿主机用户创建容器时指定--user或在 Dockerfile 设置用户容器启动后立即退出这个是最常见的“假新手问题”。它往往不是 Bug而是你没理解容器进程模型。Docker 容器只有在前台有一个活跃进程时才会保持运行。如果你启动一个普通的 Debian 容器而不运行任何常驻进程容器会立刻退出。解决办法就是让主进程在前台运行日志输出到标准输出。理解这一点后绝大多数“容器起不来”的问题都能自我排查了。时区问题我也踩过不少次。默认情况下容器内时区是 UTC你打日志或者定时任务会发现时间比本地快了 8 个小时。比较干净的做法是在运行容器时加一个环境变量docker run -e TZAsia/Shanghai my-image如果基础镜像里没有时区数据可能还需要在 Dockerfile 里安装tzdata。遇到时间不对第一时间先查这个。权限问题是生产环境绕不开的坑。容器内的进程默认以 root 身份运行安全性不好。加上容器内创建的文件在宿主机上会显示为 root 所有这会让宿主机上的普通用户没办法直接删除或编辑。建议在 Dockerfile 里用USER指令切换到非 root 用户运行应用而不是直接裸奔。写在最后的一些心得这一篇的内容基本上把我从“零基础跑起第一个容器”到“写自己的 Dockerfile 构建镜像”这个过程完整过了一遍。作为系列的第一篇我没有刻意去追求覆盖 Docker 的全部功能像编排、单机多容器应用、仓库搭建这些内容都留到后续的篇幅里展开。我在实际学习的过程中最深的体会是Docker 的命令并不难记关键是要建立一个“镜像-容器-仓库”三角关系的心智模型。只要脑子里有了这个模型遇到任何报错你都能判断出问题出在哪一侧也知道该去哪里查。很多初学者学 Docker 学着学着放弃了就是因为一开始就陷入复杂概念里比如网络模式、存储驱动、命名空间这些在初期根本不重要。把一个 Web 服务容器跑起来看到页面可以访问那种正向反馈才是坚持下去的动力。另外想分享一个小技巧不要只看别人的教程一定要自己动手操作。把教程里的命令一个个敲一遍哪怕敲错了报错了也比纯看十遍有用。遇到报错不要慌看日志记下关键词去搜索这是每个 Dcoker 使用者都必须掌握的自我解救能力。把这篇里的例子都实践一遍你就已经具备了在生产环境里使用 Docker 的基本能力。下一期我会讲容器间的协作和数据持久化的进阶用法到时候见。

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号