目录

运行第一个 Docker 容器:docker run 教程

本节将运行一个 nginx 网页服务器,并学习如何查看、进入、停止和删除容器。每一步都附有实际运行结果。

启动 nginx

docker run -d -p 8080:80 --name web nginx:1.30
$ docker run -d -p 8080:80 --name web nginx:1.30
Unable to find image 'nginx:1.30' locally
1.30: Pulling from library/nginx
ecc510c1e359: Pull complete
f4616bb1be1c: Pull complete
f1a6a629b824: Pull complete
3d774efa34e3: Pull complete
cb44c3fe542b: Pull complete
121907e00c1c: Pull complete
220a6ac36368: Pull complete
Digest: sha256:9bf97bd7714f5e24c1ccd545ecb9eb5435cb6d109c97cebb15e7e455e0239edb
Status: Downloaded newer image for nginx:1.30
b470f4d4563701824e59040cdfcd2154b4bbcca581e6d2d75cae5f2c23dbcfda

依次发生了以下事情:

  1. 本机没有 nginx:1.30 镜像(Unable to find image ... locally),因此先从 Docker Hub 下载。
  2. 镜像由多个层组成,每一行 Pull complete 都表示一层下载完成。
  3. 下载完成后,Docker 使用这个镜像创建一个新容器,并将其命名为 web。
  4. -d 让容器在后台运行,因此命令会立即结束,只打印出容器 ID(一长串十六进制字符)。

参数说明

参数含义
-ddetached,在后台运行
-p 8080:80将主机的 8080 端口映射到容器的 80 端口
--name web将容器命名为 web,之后可以用这个名称操作它
nginx:1.30镜像名称和版本(tag)

用浏览器打开

打开浏览器,输入 http://localhost:8080:

nginx 默认欢迎页面
在浏览器中打开 http://localhost:8080,看到 nginx 的欢迎页面

流量路径为:浏览器 → 主机的 8080 端口 → Docker 转发到容器的 80 端口 → 容器中的 nginx。

也可以在终端中用 curl 测试:

$ curl -s http://localhost:8080 | head -n 4
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>

查看正在运行的容器:docker ps

$ docker ps
CONTAINER ID   IMAGE        COMMAND                  CREATED         STATUS         PORTS                                     NAMES
b470f4d45637   nginx:1.30   "/docker-entrypoint.…"   7 seconds ago   Up 7 seconds   0.0.0.0:8080->80/tcp, [::]:8080->80/tcp   web
字段含义
CONTAINER ID容器 ID 的前 12 位,可以在命令中用它代替名称
IMAGE使用的镜像
COMMAND容器启动时运行的命令
CREATED / STATUS创建时间、当前状态(Up 表示正在运行)
PORTS端口映射,0.0.0.0:8080->80/tcp 就是刚才的 -p 8080:80
NAMES容器名称

查看日志:docker logs

nginx 会将每个请求记录在日志中。刚才通过浏览器和 curl 各连接了一次:

$ docker logs web
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2026/10/12 14:38:25 [notice] 1#1: using the "epoll" event method
2026/10/12 14:38:25 [notice] 1#1: nginx/1.30.5
2026/10/12 14:38:25 [notice] 1#1: built by gcc 14.2.0 (Debian 14.2.0-19)
2026/10/12 14:38:25 [notice] 1#1: OS: Linux 5.4.0-216-generic
2026/10/12 14:38:25 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2026/10/12 14:38:25 [notice] 1#1: start worker processes
2026/10/12 14:38:25 [notice] 1#1: start worker process 28
172.17.0.1 - - [12/Oct/2026:14:38:29 +0000] "GET / HTTP/1.1" 200 896 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/130.0.6723.31 Safari/537.36" "-"
172.18.0.1 - - [12/Oct/2026:14:38:31 +0000] "GET / HTTP/1.1" 200 896 "-" "curl/8.22.0" "-"

前面是 nginx 启动时的消息,可以看到版本为 nginx/1.30.5。最后两行是刚才的请求记录:一行来自浏览器(User-Agent 是浏览器),另一行来自 curl。加上 -f 可以持续跟踪新日志(按 Ctrl + C 退出):

docker logs -f web

进入容器:docker exec

docker exec 可以在正在运行的容器中执行命令:

$ docker exec web nginx -v
nginx version: nginx/1.30.5

$ docker exec web ls /usr/share/nginx/html
50x.html
index.html

加上 -it 可以打开交互式 shell,进入容器四处看看:

$ docker exec -it web bash
root@b470f4d45637:/# cat /etc/os-release | head -n 2
PRETTY_NAME="Debian GNU/Linux 13 (trixie)"
NAME="Debian GNU/Linux"
root@b470f4d45637:/# ls /etc/nginx
conf.d
fastcgi_params
mime.types
modules
nginx.conf
scgi_params
uwsgi_params
root@b470f4d45637:/# ps aux
bash: line 1: ps: command not found
root@b470f4d45637:/# exit
exit

从输出可以看到几件事:

  • nginx 官方镜像基于 Debian 13(trixie)。
  • 提示符中的 b470f4d45637 是容器的主机名,默认就是容器 ID。
  • 容器里没有 ps 命令。官方镜像只包含运行 nginx 所需的内容,许多常见工具都被移除了,这是正常的。需要调试工具时,可以临时安装(apt-get update && apt-get install -y procps),也可以使用 docker top 从外部查看。

输入 exit 退出,容器仍会继续运行。

修改网页内容

在容器中修改首页,然后刷新浏览器:

$ docker exec web sh -c 'echo "<h1>Hello from my first container</h1>" > /usr/share/nginx/html/index.html'

$ curl -s http://localhost:8080
<h1>Hello from my first container</h1>
修改后的 nginx 首页
修改容器中的 index.html 后,浏览器立即显示新内容

直接修改容器中的文件只适合临时测试。删除容器后,修改内容也会消失。正确做法是将网页文件挂载到容器中(参见 Volume),或写入 Dockerfile。

停止、启动和删除

$ docker stop web
web

$ docker ps -a
CONTAINER ID   IMAGE         COMMAND                  CREATED              STATUS                              PORTS     NAMES
b470f4d45637   nginx:1.30    "/docker-entrypoint.…"   12 seconds ago       Exited (0) Less than a second ago             web
786dd898c04b   hello-world   "/hello"                 About a minute ago   Exited (0) About a minute ago                 frosty_shirley

$ docker start web
web

$ curl -s http://localhost:8080
<h1>Hello from my first container</h1>

$ docker rm web
Error response from daemon: cannot remove container "web": container is running: stop the container before removing or force remove

$ docker rm -f web
web

$ docker ps -a
CONTAINER ID   IMAGE         COMMAND    CREATED              STATUS                          PORTS     NAMES
786dd898c04b   hello-world   "/hello"   About a minute ago   Exited (0) About a minute ago             frosty_shirley
  • docker stop:停止容器,容器仍然存在,可以通过 docker ps -a 查看,状态为 Exited。
  • docker start:重新启动已有容器,刚才修改的首页也还在。
  • docker rm:删除已停止的容器。对正在运行的容器执行此命令会出现上面的错误 container is running,需要先运行 docker stop,或加上 -f 强制删除。

在 docker ps -a 的列表中,还能看到上一节运行过的 hello-world 容器:它运行完就退出了(Exited (0)),但没有被删除。未指定 --name 的容器会获得一个随机名称,例如 frosty_shirley。

删除容器后,刚才修改的首页也会一起消失。使用同一个镜像再启动一个新容器,看到的将是原来的 nginx 欢迎页面。

运行一次性命令

并非所有容器都需要长期运行。下面这个容器只运行一条命令就会退出,--rm 会让它退出后自动删除:

$ docker run --rm ubuntu:26.04 cat /etc/os-release
Unable to find image 'ubuntu:26.04' locally
26.04: Pulling from library/ubuntu
06ad70e463aa: Pull complete
4e07a0f12b2c: Pull complete
Digest: sha256:f144425ff09be612d6d9ad965196e9cdc23dae1f42110a8a11a3e9a8198759f7
Status: Downloaded newer image for ubuntu:26.04
PRETTY_NAME="Ubuntu 26.04.1 LTS"
NAME="Ubuntu"
VERSION_ID="26.04"
VERSION="26.04.1 LTS (Resolute Raccoon)"
VERSION_CODENAME=resolute
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=resolute
LOGO=ubuntu-logo

这个 Ubuntu 容器只有 Ubuntu 的用户空间文件,没有启动进程,也没有桌面,从启动到结束只需一瞬间。

使用 Docker Desktop 图形界面操作

在 Windows 和 macOS 上,也可以在 Docker Desktop 中用鼠标完成上述每一步。

搜索并下载镜像

在顶部的搜索框中输入镜像名称,选择所需版本(Tag),点击 Pull 下载,或直接点击 Run:

Docker Desktop 搜索镜像
在 Docker Desktop 中搜索镜像,可以在右侧选择 Tag 并点击 Pull 或 Run。图片来源:Docker 官方文档(Apache-2.0)

配置并运行容器

点击 Run 后展开 Optional settings,可以设置容器名称、端口、Volume、环境变量,分别对应 docker run 的 --name、-p、-v、-e:

Docker Desktop 运行新容器的设置窗口
Host port 填入 8080,相当于 docker run -p 8080:80。图片来源:Docker 官方文档(Apache-2.0)

查看和管理容器

左侧菜单中的 Containers 会列出所有容器,相当于 docker ps -a。点击 Port(s) 列中的链接可以直接用浏览器打开,右侧按钮可用于停止、重新启动和删除容器:

Docker Desktop 容器列表
Containers 页面:状态、端口和操作按钮。图片来源:Docker 官方文档(Apache-2.0)

点击某个容器,可以看到 Logs(相当于 docker logs)、Exec(相当于 docker exec)、Files(浏览容器中的文件)等选项卡:

Docker Desktop 容器的 Files 选项卡
Files 选项卡可以直接浏览和编辑容器中的文件。图片来源:Docker 官方文档(Apache-2.0)

图形界面便于查看状态,但实际工作中仍以命令为主:命令可以写入文档和脚本,在 Linux 服务器上也只能通过命令操作。

Windows 用户:命令写法差异

本教程中的命令以 Linux/macOS 的 bash 为准。在 Windows 上,Docker 命令本身完全相同,但终端(shell)的语法不同:

写法Linux / macOS(bash)Windows PowerShellWindows CMD
当前文件夹$(pwd)${PWD}%cd%
命令换行行尾 \行尾 `行尾 ^
环境变量$HOME$env:USERPROFILE%USERPROFILE%
从文件输入 <支持不支持支持

本教程中需要使用不同写法的命令,都附有 Linux / macOS、Windows PowerShell、Windows CMD 三个选项卡,点击后整页都会切换为相应写法。例如,将当前文件夹中的 site 挂载到 nginx:

docker run -d -p 8080:80 -v "$(pwd)/site:/usr/share/nginx/html:ro" nginx:1.30
docker run -d -p 8080:80 -v "${PWD}/site:/usr/share/nginx/html:ro" nginx:1.30
docker run -d -p 8080:80 -v "%cd%/site:/usr/share/nginx/html:ro" nginx:1.30

几个常见问题(实际错误信息见常见错误信息):

  • 在 PowerShell 中写 "$PWD:/app" 会出错,必须写成 "${PWD}:/app"。
  • PowerShell 不支持 <,还原数据库时需要改用 docker cp,各数据库章节都附有相应写法。
  • 在 Windows 上编辑的 shell 脚本如果使用 CRLF 换行,放入容器运行时会出现 no such file or directory。

也可以在 WSL(例如 Ubuntu)的终端中使用 Docker Desktop,此时直接使用本教程中的 Linux 写法即可。

重点回顾

  • docker run -d -p 主机端口:容器端口 --name 名称 镜像 在后台启动容器并映射端口。
  • docker ps 查看正在运行的容器,-a 会包含已停止的容器。
  • docker logs 查看输出,docker exec -it 容器 sh 进入容器。
  • docker stop / start / rm -f 用于控制和删除容器;直接修改容器中的文件只适合临时测试。

动手练习

  1. 再启动一个 nginx,并映射到主机的 8081 端口:docker run -d -p 8081:80 --name web2 nginx:1.30,打开 http://localhost:8081 确认结果。
  2. 用 docker ps 确认两个容器同时运行,并且分别映射到不同的主机端口。
  3. 删除这两个容器:docker rm -f web web2。

下一节将深入介绍镜像:名称和标签的规则,以及如何下载、查看和删除镜像。

常见问题

http://localhost:8080 打不开?

先用 docker ps 确认容器正在运行,并且 PORTS 列中有 0.0.0.0:8080->80/tcp。如果 8080 被其他程序占用,docker run 会显示 port is already allocated,请改用 -p 8081:80。

为什么容器里没有 ps、vim 这些命令?

官方镜像只包含运行服务所需的内容,这样镜像更小、漏洞更少。调试时可以用 docker exec 运行镜像中已有的工具,或另外启动一个包含工具的容器。

容器 ID 和名称可以互换使用吗?

可以。命令中既可以使用名称,也可以使用 ID 的前几位(只要不与其他容器重复)。

更新于 2026年10月14日