Docker HelloWorld 的实战入门其实是一条非常直接的路线:安装 Docker 引擎,运行 docker run hello-world,观察镜像拉取与容器启动的输出;接着用一个极简 Dockerfile 构建自定义镜像、运行带端口映射和卷挂载的容器,理解镜像层、容器与宿主机资源的映射以及网络模型。本文以一步步实操为主线,解释每条命令的本质和常见故障,帮助你从“看见输出”到“理解原理并能排查问题”。

为什么先做 HelloWorld?先弄清楚目的
如果你刚接触 Docker,直接跳到复杂应用(微服务、CI/CD)会被细节吓到。HelloWorld 是一种“最小可运行单元”验证手段:它能告诉你 Docker 是否安装正确、网络是否可用、镜像仓库是否可访问、以及容器能否启动与输出预期信息。更重要的是,做完 HelloWorld 后,你会对镜像拉取、容器启动流程有一个清晰的心理模型,后面所有概念都可以在这个模型上扩展。
准备工作:环境与安装要点
支持的平台
- Linux(推荐 Ubuntu、Debian、CentOS 等发行版)
- macOS(使用 Docker Desktop)
- Windows(Windows 10/11 Pro 使用 Docker Desktop;Windows Server 有专门安装方式)
快速安装要点(概述)
- Linux:使用官方仓库安装 docker-ce,安装后启动并加入 docker 组以便无 sudo 运行。
- macOS / Windows:安装 Docker Desktop,注意开启虚拟化(HyperKit / WSL2 for Windows)。
- 网络:如果在公司或国内网络,可能需要配置镜像加速器或代理。
典型安装命令(Ubuntu 示例)
sudo apt update
sudo apt install -y apt-transport-https ca-certificates curl gnupg lsb-release
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo \
"deb [arch=$(dpkg --print-architecture) 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 usermod -aG docker $USER
安装细节会随系统版本变化,上面只是一个常见流程;如果遇到问题,参考 Docker 官方文档或你所在发行版的社区说明。
第一步:运行 HelloWorld 镜像并观察发生了什么
运行命令
docker run hello-world
典型输出解析
- 如果本地没有 hello-world 镜像,Docker 会向 Docker Hub 发起拉取请求。
- 镜像拉取完成后,Docker 会基于该镜像创建容器并启动,容器会输出一段信息,然后退出(这是一个短生命周期容器示例)。
- 输出包含:“Hello from Docker!” 类型的信息,说明引擎、镜像仓库访问与容器运行都正常。
如果没有输出或报错,先检查
- Docker 服务是否启动:
sudo systemctl status docker - 用户权限:是否需要 sudo 或是否添加到 docker 组
- 网络访问:能否访问 Docker Hub(公司网络可能被防火墙或代理限制)
- DNS 问题:容器能否解析域名,可临时使用镜像加速器
从 HelloWorld 到自定义镜像:编写一个最小示例
真正学会 Docker,不只是能运行别人写好的镜像,而是能把应用打包成镜像、配置运行时。下面我们用一个极简的 Python Web 应用演示从代码到镜像再到运行的全流程。
示例目录结构
hello-docker/
├── app.py
└── Dockerfile
app.py(极简 Flask 示例)
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return "Hello, Docker!"
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
Dockerfile(逐行解释)
FROM python:3.10-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 5000
CMD ["python", "app.py"]
- FROM:基于官方基础镜像,形成镜像层的起点。
- WORKDIR:设定容器内部工作目录,后续命令都会基于此目录执行。
- COPY:把代码拷贝进镜像,产生新的镜像层。
- RUN:在镜像构建阶段执行命令(如安装依赖),结果写入镜像层。
- EXPOSE:声明容器监听端口(文档作用),运行时需用 -p 映射到宿主机端口。
- CMD:容器启动时执行的默认命令,可被 docker run 后的参数覆盖。
构建与运行
# 构建镜像
docker build -t my-hello:1.0 .
# 运行容器并映射端口
docker run -d -p 8080:5000 --name my-hello-container my-hello:1.0
之后在浏览器访问 http://localhost:8080 就能看到 “Hello, Docker!”。如果是在远程服务器,注意安全组/防火墙设置。
深入理解:镜像、容器、层与存储
这些名词常被混用,但理解它们之间的区别很重要。
- 镜像(Image):只读模版,由多个只读层组成(每次 RUN/COPY 等会产生新层)。镜像不运行。
- 容器(Container):镜像的一个可写实例,运行时为镜像添加可写层,容器有生命周期(创建、启动、停止、退出、删除)。
- 层(Layers):镜像由层叠加构成,重复利用相同层可以节省空间和拉取时间。
- 卷(Volumes):用于持久化数据,独立于容器生命周期,适合数据库或日志存储。
典型命令速览表
| 操作 | 命令 | 说明 |
| 列出容器 | docker ps -a |
查看运行和已停止的容器 |
| 查看镜像 | docker images |
列出本地镜像 |
| 删除容器 | docker rm <container> |
移除停止状态的容器 |
| 删除镜像 | docker rmi <image> |
删除本地镜像 |
常见问题与排查技巧(基于 HelloWorld 和最小应用)
1. docker run 报错:permission denied
通常是因为当前用户没有访问 Docker socket 的权限。临时用 sudo,长期方案是把用户加入 docker 组并重新登录:
sudo usermod -aG docker $USER
2. 无法拉取镜像(超时、DNS 解析失败)
- 确认宿主机能 ping registry-1.docker.io(或使用 curl 测试)。
- 在国内环境常用镜像加速器(阿里云、DaoCloud 等),也可配置 /etc/docker/daemon.json 设置 registry-mirrors。
3. 端口映射后无法访问
- 检查容器内服务是否监听 0.0.0.0 而非 127.0.0.1(app.run(host=’0.0.0.0′))。
- 确认宿主机防火墙或云安全组已开放对应端口。
- 使用
docker logs <container>查看容器输出。
4. 镜像构建慢或失败
- 把不常变动的依赖安装步骤放在 Dockerfile 前面,利用缓存加速。
- 使用
.dockerignore排除不必要的文件(如 node_modules、.git)。 - 读懂失败信息,常见是 pip/npm 安装过程中的网络或编译依赖问题。
扩展:把 HelloWorld 变成可复用的开发流程
上面的示例是“单镜像单容器”。工程化通常需要考虑:多环境(dev/prod)配置、镜像安全扫描、CI/CD 构建与镜像推送、以及容器编排(Docker Compose 或 Kubernetes)。这里给出一些实际可用的建议,便于把简单流程推广到团队使用。
1. 使用 docker-compose 管理多服务
version: '3.8'
services:
web:
build: .
ports:
- "8080:5000"
volumes:
- .:/app
environment:
- FLASK_ENV=development
Compose 在开发阶段非常方便:代码改动可通过卷挂载实时生效,配置变更也更集中。
2. 镜像版本管理与镜像仓库
- 使用语义化标签(如 v1.0.0、latest)并在 CI 中自动打标签。
- 推送到私有仓库或公有仓库:
docker tag与docker push。
3. 安全与最小化镜像
- 尽量使用瘦身基础镜像(alpine 或 slim),但注意兼容性和二进制依赖的问题。
- 扫描镜像漏洞(例如使用 Trivy、Clair 等工具)。
调试技巧与进阶命令
docker logs <container>:查看容器输出日志。docker exec -it <container> /bin/sh:进入正在运行的容器交互式调试(对于没有 shell 的最小镜像需提前准备调试工具)。docker inspect <container|image>:查看容器或镜像的底层元数据,例如挂载点、网络设置、环境变量等。docker stats:查看容器资源占用实时统计。
几个容易被忽视的小细节(实践中会踩的坑)
- 镜像中使用相对路径时,确认 WORKDIR 与 COPY 的目标一致。
- 不要在镜像里写入敏感信息(密码、密钥),使用环境变量或 secret 管理。
- 开发环境用卷挂载非常方便,但在生产环境不要把源码直接挂载到容器里。
- 注意容器时钟和宿主机的时区差异,日志时间不一致会很迷惑。
参考阅读(书名与工具名,方便后续深挖)
- 《Docker — 从入门到实践》
- Docker 官方文档(Docker Engine、Dockerfile、Compose)
- Trivy(容器镜像扫描工具)
说到这里,可能你已经在机器上试过 docker run hello-world,也构建并运行了那台小小的 Flask 服务。实操是关键:当遇到问题,回到“谁在做什么”这个问题就能把错误一步步拆解——镜像是不是存在?容器里服务有没有监听?端口是不是映射?权限是不是受限?慢慢你会发现,Docker 的很多抽象背后都是很朴素的系统调用与文件映射。好了,我先放下键盘去再跑一遍示例(顺便检查下那个忘记加到 .dockerignore 的 node_modules),你要是想看一个更完整的 CI/CD 示例或者 Kubernetes 部署,我可以再接着写。