2. Docker 基础操作:镜像拉取、运行容器、进入容器、文件拷贝、端口映射

说实话,很多初学者觉得 Docker 基础操作就是背几个命令。但我告诉你,真正干活的时候,命令背后那些细节才是坑。我记得自己刚用 Docker 那会儿,一个端口映射写错,调试了一下午。所以今天咱们把这五个操作彻底掰开揉碎。

2.1 镜像拉取:从哪儿拿,怎么拿

镜像就像软件的安装包。Docker Hub 是全球最大的镜像仓库,但我建议你在公司场景下先配置一个国内镜像加速器,否则 pull 一个几 GB 的镜像能等到怀疑人生。

最常用的拉取命令长这样:

docker pull nginx:latest

这条命令会从 Docker Hub 拉取最新版的 nginx 镜像。你也可以指定版本号,比如 nginx:1.25。我个人习惯在生产环境里总是指定精确版本,因为 latest 可能会变——你想想看,今天跑得好好的,明天一拉变成新版本,兼容性问题就来了。

拉取过程中会显示分层下载的进度。每一层都是一个只读文件系统,Docker 会缓存它们。如果你拉取同一个镜像的不同版本,共享的层不会被重复下载。这个机制在实际项目中非常有用——我曾在 CI 流水线里利用它把构建时间从 8 分钟压到 2 分钟。

小技巧: 查看本地已有镜像用 docker images 或 docker image ls。想删除镜像用 docker rmi <镜像名>,但注意要先删掉基于它的所有容器。

2.2 运行容器:镜像变实例

镜像拉下来了,怎么让它跑起来?用 docker run。这是整个 Docker 里最核心、参数最多的一个命令。咱们先看最简启动:

docker run nginx:latest

执行后终端会被 nginx 的前台日志刷屏。按 Ctrl+C 可以停止。但实际使用中我们通常让它后台运行:

docker run -d nginx:latest

-d 代表 detach,意思是在后台运行。命令会返回一串容器 ID,像 abc123def456。你可以用 docker ps 查看正在运行的容器列表。

有一个参数我几乎每次都用,就是 --name:

docker run -d --name my-nginx nginx:latest

给容器起个名字,后面操作起来就不用记那一长串 ID 了。我在管理二十几个微服务时,名字就是救命稻草。

参数 含义 常用组合
-d 后台运行 docker run -d --name web nginx
-it 交互式终端(后面会用到) docker run -it ubuntu bash
--rm 容器退出后自动删除 测试环境常用
-p 端口映射(详见 2.5) -p 8080:80
-v 挂载卷/目录 -v /host/path:/container/path

2.3 进入容器:和容器内部打交道

容器跑起来了,你想进去看看文件、跑个命令、查个日志,怎么办?用 docker exec。

先启动一个持续运行的容器,比如刚才的 nginx:

docker run -d --name my-nginx nginx:latest

然后进入它的 bash 环境:

docker exec -it my-nginx bash

进去之后就像登录了一台 Linux 机器。你可以执行 ls、cat、apt update 等操作。但要注意,很多镜像为了保持精简,并没有安装完整工具链。比如 apt 可能不存在,你得用 apt-get。我遇到过最坑的情况是 vi 都没有,只能靠 echo 和重定向来修改配置文件——嗯,后来我提前在 Dockerfile 里装好了 vim-tiny。

坑: 用 docker exec -it my-nginx bash 时,如果容器里没有 bash,可以试试 sh 或 ash。如果连 shell 都没有,你只能通过 docker cp 来操作文件了(下面会讲)。

除了交互式进入,你还可以直接执行单次命令:

docker exec my-nginx cat /etc/nginx/nginx.conf

这比进入容器再 cat 要快得多。我在排查问题时经常这样用——一条命令出结果,不用来回切换窗口。

2.4 文件拷贝:宿主机 ↔ 容器

有时你需要把宿主机上的文件拷进容器,或者把容器里的日志、配置拷出来。别去容器里装 scp,有现成的 docker cp。

把宿主机文件拷入容器:

docker cp ./my-config.conf my-nginx:/etc/nginx/conf.d/

把容器文件拷到宿主机:

docker cp my-nginx:/var/log/nginx/access.log ./

这个命令支持目录递归拷贝。我曾经在项目上线时,需要把一批 SSL 证书放进六个容器——用 docker cp 写个循环脚本,几秒钟就搞定了,比手动进容器粘贴效率高多了。

有一点要小心:docker cp 拷贝时不会自动创建不存在的目录。如果目标路径缺少中间目录,会报错。你需要在容器里提前用 docker exec 创建好。

2.5 端口映射:让外面能访问容器

容器默认有独立的网络命名空间。你在容器里启动了一个 nginx 监听 80 端口,但宿主机的 80 端口上什么都没跑——除非你做端口映射。

在 docker run 时加上 -p 参数:

docker run -d --name my-nginx -p 8080:80 nginx:latest

这条命令把宿主机的 8080 端口映射到容器的 80 端口。访问 http://localhost:8080 就能看到 nginx 欢迎页了。

映射规则是 宿主机端口:容器端口。可以多个端口映射:

docker run -d --name my-app -p 8080:8080 -p 8443:8443 my-app-image
经验之谈: 我曾遇到过宿主机 80 端口已经被其他服务占用的场景。这时候用 docker run -p 8888:80 改为非标准端口,同时在前端 nginx 反向代理中加一条转发规则即可。千万不要硬改宿主机已有服务端口。

还有一种是随机端口映射:

docker run -d -P nginx:latest

大写 -P 会让 Docker 自动把容器内暴露的端口(Dockerfile 中的 EXPOSE)映射到宿主机的随机高位端口。用 docker ps 查看具体映射关系。这在测试环境偶尔用用,但生产里还是手动指定更可控。

本章知识图谱

下面这张图把五个操作串在一起,方便你理清关系:

Docker 基础操作流程 ① 拉取镜像 ② 运行容器 ③ 进入容器 ④ 文件拷贝 ⑤ 端口映射 宿主机 外部访问 💡 箭头方向表示操作顺序。③进入容器与④文件拷贝可以交替使用,⑤端口映射在②运行容器时配置。 虚线表示宿主机与外部网络之间的映射关系。
练习建议: 现在你可以打开终端,按照上面的步骤顺序练一遍:docker pull nginx → docker run -d --name test-nginx -p 8888:80 nginx → docker exec -it test-nginx bash → 在容器里创建一个文件 → exit 后用 docker cp 拷出来。整个过程不要看笔记,自己敲两遍就熟了。

最后提醒一句:docker run 和 docker start 不一样。前者是“创建并启动一个新容器”,后者是“启动一个已存在的停止状态的容器”。我刚开始就搞混过——写了个启动脚本用的 docker start,结果容器每次重建后配置全丢了。