【Docker】P2 Docker 命令:从Nginx部署到镜像分享的全流程指南

目录

欢迎来到本期的 Docker 教程!今天,我们将通过一个完整的流程化实例,带你走过 Docker 最核心的命令操作。

这个完整的流程为:

bash 复制代码
下载镜像 ➡️ 启动容器 ➡️ 修改应用 ➡️ 保存为新镜像 ➡️ 分享社区

镜像操作 (Image)

在 Docker 的世界里,一切都始于镜像 (Image)。你可以把镜像想象成一个"安装包",它是一个只读的模板,打包了运行应用所需的所有文件、依赖和配置。

镜像操作的主要命令包含:

  • 搜索镜像: docker search
  • 下载镜像: docker pull
  • 查看本地镜像: docker images
  • 删除镜像: docker rmi

检索与发现镜像

我们首先需要一个 Nginx 镜像。去哪里找呢?

  • 命令行检索docker search): 你可以使用 docker search nginx 来快速查找。
  • 更推荐: 访问 Docker Hub ,官方的镜像仓库。在这里搜索 nginx,你能直观的看到社区中所有的 nginx 镜像文件,包含:
    • Official Image (官方镜像): 带有 "Official" 标签,由 Docker 官方或应用官方维护,是我们的首选。
    • 社区镜像: 如 bitnami/nginx,由第三方维护。
    • 下载量 (Pulls) 和星标 (Stars): 这是判断镜像质量和受欢迎程度的重要依据。

下载镜像

让我们来使用官方的 nginx 镜像。

bash 复制代码
docker pull nginx

这个命令其实是一个简写。完整的命令格式是

bash 复制代码
docker pull [OPTIONS] NAME[:TAG|@DIGEST]
  • NAME 为镜像名,这里是 nginx。
  • [:TAG] 标签版本号,用于区分不同版本,选填,默认值为 :latest

查看本地镜像

下载完成后,我们使用 docker images 来查看本地已有的所有镜像。

bash 复制代码
docker images

你会看到一个列表:

bash 复制代码
REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
nginx         latest    605c75e6e14c   3 weeks ago    141.5MB

让我们来详细解析每一列的含义:

  • REPOSITORY: 镜像仓库名称
  • TAG: 镜像标签(版本)
  • IMAGE ID: 镜像的唯一标识符,一个SHA256哈希值
  • CREATED: 镜像的创建时间
  • SIZE: 镜像文件占用的存储空间

删除镜像

如果某个镜像不再需要,可以使用 docker rmi (remove image) 删除它。

bash 复制代码
docker rmi [OPTIONS] [IMAGE_ID 或 REPOSITORY:TAG]
# 例如:docker rmi 605c75e6e14c
  • 注意: 如果一个镜像已经被某个容器(哪怕是已停止的容器)所使用,你是无法直接删除它的。你必须先删除所有使用该镜像的容器(详见下文 docker rm),或者在命令中 [OPTIONS] 部分使用 -f 强制删除(不推荐)。

容器操作 (Container)

有了镜像(安装包),我们就可以运行它,创建容器 (Container)。容器是镜像的运行时实例,是一个被隔离的、正在运行的应用环境。

容器操作的主要命令包含:

  • 启动容器: docker run
  • 查看容器: docker ps
  • 删除容器: docker rm
  • 停止容器: docker stop
  • 启动容器: docker start
  • 重启容器: docker restart

启动第一个容器

我们以最简单的方式启动 Nginx:

bash 复制代码
docker run nginx

问题出现: 你会发现,Nginx 启动后,你的命令行被占用了,日志在前台 不断输出。如果你按下 Ctrl+C 退出,容器也会随之停止。这显然不是我们想要的。

对此,我们的解决策略为在 run 命令中添加 -d 的 OPTIONS,具体原因我们稍后详述。

bash 复制代码
docker run -d nginx

查看容器

我们如何查看容器的状态?应用 docker ps 命令

  • docker ps:查看正在运行中的容器。
  • docker ps -a:查看所有的容器(包括已停止的)。

我们执行 docker ps

bash 复制代码
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS                      PORTS     NAMES
f3e6a0d4a7d1   nginx     "/docker-entrypoint...."   2 minutes ago    UP 2 minutes ago              jolly_bose

我们来解析 docker ps 展示出的列的含义:

  • CONTAINER ID:容器的唯一身份ID
  • IMAGE: 创建该容器所用的镜像
  • COMMAND: 容器启动时执行的命令,命令为内部命令,忽略
  • CREATED: 容器的创建时间
  • STATUS: 容器当前的状态。Up (运行中), Exited (已停止)。
  • PORTS: 容器的端口映射情况(稍后详述)。
  • NAMES: 容器的名称。如果你不指定,Docker 会分配一个随机的名称,如本示例中的 jolly_bose。

容器的生命周期管理

假设,我们来清理一个"已停止"的容器 my_app。

删除

bash 复制代码
docker rm my_app
# 或者使用 ID: docker rm f3e6a0d4a7d1

停止

docker rm 只能删除已停止的容器。如果容器正在运行,你需要先停止它:

bash 复制代码
# 假设有一个运行中的容器 "my_app"
docker stop my_app
# 或者使用 ID: docker stop f3e6a0d4a7d1

强制删除

如果你想一步到位,可以使用 -f 强制删除一个正在运行的容器(它会先 stoprm)。

bash 复制代码
docker rm -f my_app
# 或者使用 ID: docker rm -f f3e6a0d4a7d1

启动/重启

对于已停止的容器,可以使用 docker start 重新启动它。

bash 复制代码
docker start jolly_bose
# 或者使用 ID: docker start f3e6a0d4a7d1
docker restart jolly_bose # 重启
# 或者使用 ID: docker restart f3e6a0d4a7d1

深入 docker run

docker run 是 Docker 中最重要、最复杂的命令。我们现在用更合理的方式来启动 Nginx,解决之前遇到的两个问题:

  1. 前台运行,占用终端。
  2. 容器运行了,但我们从主机(电脑)无法访问。

为了解决上述两个问题,我们对 run 补充三个 OPTIONS:

  • -d:运行在后台
  • --name:起名
  • -p:端口映射

后台运行与命名

我们使用 -d (Detached) 参数,让容器在后台运行 。同时,使用 --name 给容器起一个好记的名字

bash 复制代码
docker run -d --name mynginx nginx

执行后,它只会返回一个容器ID,终端不会被占用。

此时,我们用 docker ps 查看:

bash 复制代码
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS     NAMES
a1b2c3d4e5f6   nginx     "/docker-entrypoint...."   5 seconds ago   Up 4 seconds   80/tcp    mynginx

STATUS 显示 UpNAMES 是我们指定的 mynginx

端口映射

现在容器在后台运行了。我们尝试在浏览器访问 http://localhost:80http://IP:80 失败了。

这是为什么呢? Docker 容器是隔离的。当你启动 mynginx 容器时,它在自己的"小黑屋"(独立的网络空间)里运行。Nginx 在这个小黑屋里监听了 80 端口。但是,我们的主机(你的电脑)并不知道这个小黑屋的存在,更无法访问它内部的 80 端口。

我们需要在主机和小黑屋之间架设一座桥梁,这就是端口映射 (-p)

bash 复制代码
# 语法: -p [宿主机端口]:[容器端口]

让我们删掉刚才的容器,用正确的方式重新启动:

bash 复制代码
# 1. 先停止并删除旧的
docker rm -f mynginx

# 2. 启动新容器,并添加端口映射
docker run -d --name mynginx -p 88:80 nginx

命令解析:

  • -p 88:80:将主机的 88 端口映射到容器的 80 端口。

现在,访问 http://localhost:88 的所有请求,都会被 Docker 自动转发到 mynginx 容器内部的 80 端口上。


修改 Nginx 首页

我们成功运行了 Nginx,但我们想修改默认的欢迎页面。此时,我们需要进入 mynginx 容器的内部,修改 Nginx 存放 index.html 的默认路径(通常是 /usr/share/nginx/html

主要涉及命令:

  • exec:进入到运行的容器中

进入运行中的容器

docker exec 命令允许我们在一个正在运行的容器中执行命令。

go 复制代码
docker exec -it mynginx /bin/bash

命令解析:

  • exec:进入容器固定指令,无他意
  • -it:这是两个参数的合写,无需深究:
    • -I:保持标准输入(STDIN)打开,允许我们与 shell 交互
    • -t:分配一个伪终端(pseudo-TTY),给我们一个像在真实服务器上操作的命令行提示符
  • mynginx:目标容器的名称
  • /bin/bash:我们要在容器内执行的命令。bash 是一个常见的 shell(有些轻量级镜像可能只有 /bin/sh)。

修改 html 文件

下一步,让我们来修改这份 index.html 文件:

bash 复制代码
cd /usr/share/nginx/html
# 查看文件:
ls
# 你会看到 index.html 和 50x.html
# 修改 index.html
echo "<h1>Hello! This is My Custom Nginx Page!</h1>" > index.html

验证与思考

此时,回到我们的浏览器,刷新 http://localhost:88。你会发现页面内容已经变成了 "Hello! This is My Custom Nginx Page!"。

实际上,读者在实操时也能感受到,每次都 exec 进去修改文件非常不方便,而且如果容器被删除(docker rm mynginx),所有修改都会丢失。 后面,我们将介绍更实用的技能,应用 Volume(卷)映射 (-v),将主机目录直接映射 到容器内,实现文件持久化和实时同步


保存容器为新的镜像文件

我们已经修改了 mynginx 容器。如果我们希望把这个"被修改过的状态"保存下来,变成一个新的镜像(例如 my-custom-nginx:1.0),以便将来重复使用或分享,该怎么办?

主要涉及命令:

  • commit:容器封装为镜像
  • save -o:镜像保存为 .tar 文件
  • load -I:.tar 文件导入为镜像

提交容器

docker commit 可以从一个容器的当前状态,封装打包为一个新的镜像。

bash 复制代码
docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]

OPTIONS 常用选项:

  • -a:作者(Author),例如 "Your Name"
  • -m:提交信息(Message),类似 Git commit message

操作: 我们将正在运行的 mynginx 容器,提交为一个名为 my-custom-nginx、标签为 1.0 的新镜像。

bash 复制代码
docker commit -a "My Blog User" -m "Customized index.html" mynginx my-custom-nginx:1.0

验证: 执行 docker images

bash 复制代码
REPOSITORY          TAG       IMAGE ID       CREATED          SIZE
my-custom-nginx     1.0       a9c5b0c8d6e3   5 seconds ago    141.5MB  <-- 我们新创建的
nginx               latest    605c75e6e14c   3 weeks ago      141.5MB

我们成功制作了一个新镜像!

镜像的导入与导出

docker commit 创建的镜像是保存在本地的。如果我想把这个镜像拷贝给没有网络的同事,该怎么办?

  • 保存 (save) docker save 命令可以将一个镜像打包成一个 .tar 文件。

    bash 复制代码
    docker save -o my-nginx-image.tar my-custom-nginx:1.0
    • -o:指定输出文件(output)。执行后,当前目录会多一个 my-nginx-image.tar 文件。
  • 加载 (load): 你的同事拿到这个 .tar 文件后,使用 docker load 命令将其导入到自己的 Docker 中。

    bash 复制代码
    docker load -i my-nginx-image.tar
    • -i:指定输入文件(input)。执行后,再 docker images 就能看到 my-custom-nginx:1.0 了。

分享镜像

将镜像打包成 .tar 文件只适合小范围分享。如果我们希望全世界的开发者都能使用我们的镜像,我们应该将其分享到 Docker Hub。注意,需要科学上网。

主要涉及命令:

  • login:登录官方 Hub 系统
  • tag:更改镜像名称为符合官方格式要求的名称
  • push:将本地镜像推送到全世界都可以访问的 docker hub 社区中

登录仓库

首先,你需要在 Docker Hub 网站注册一个账号。假设你的用户名是 myusername。 然后在命令行登录:

bash 复制代码
docker login
# Username: myusername
# Password: 
# Login Succeeded

标记镜像

在登录完成后,标记镜像是非常关键的一步。如果你想把镜像推送到 Docker Hub,你必须给镜像一个符合官方规范要求的名称。我们可以应用 tag 命令来重命名。

Docker Hub 对于镜像名称的规范是:[你的用户名]/[仓库名]:[标签]

我们本地的镜像叫 my-custom-nginx:1.0,这不符合规范。我们需要使用 docker tag 给它起一个"别名":

bash 复制代码
# 格式: docker tag [源镜像] [目标镜像(带用户名)]
docker tag my-custom-nginx:1.0 myusername/my-custom-nginx:1.0

验证: 再次执行 docker images,你会发现:

bash 复制代码
REPOSITORY                    TAG       IMAGE ID
my-custom-nginx               1.0       a9c5b0c8d6e3
myusername/my-custom-nginx    1.0       a9c5b0c8d6e3  <-- 新增的、符合 Docker Hub 规范的
nginx                         latest    605c75e6e14c

它们共享同一个 IMAGE ID,本质上是同一个镜像的两个不同标签。

推送镜像

最后,将我们新标记的镜像推送到 Docker Hub:

bash 复制代码
docker push myusername/my-custom-nginx:1.0

等待上传完成后,任何人(包括你自己)在世界上任何一台安装了 Docker 的机器上,都可以通过执行 docker pull myusername/my-custom-nginx:1.0 来获取你修改过的 Nginx 镜像了!


总结

恭喜你!我们从一个最基础的 nginx 官方镜像出发,经历了 pull, run, ps, exec, commit, tag, push 等一系列核心操作,走完了一个完整的 Docker"开发-打包-分发"的生命周期。

你是否想继续了解如何使用 Dockerfile 来自动化构建镜像,或者如何使用 Volume 来管理持久化数据?请期待后续博文!


2025.10.30 G38 回北京途中

相关推荐
Wang's Blog8 小时前
Nestjs框架: 微服务容器化部署与网络通信解决方案
docker·微服务·云原生·架构·nestjs
Blossom.1188 小时前
把AI“编”进草垫:1KB决策树让宠物垫自己报「如厕记录」
java·人工智能·python·算法·决策树·机器学习·宠物
芒克芒克8 小时前
ssm框架之Spring(上)
java·后端·spring
消失的旧时光-19438 小时前
Android ble理解
java·kotlin
晨晖28 小时前
SpringBoot的yaml配置文件,热部署
java·spring boot·spring
鬼火儿8 小时前
1.2 redis7.0.4安装与配置开机自启动
java·后端
小马哥编程8 小时前
【软考架构】案例分析-对比MySQL查询缓存与Memcached
java·数据库·mysql·缓存·架构·memcached
一 乐8 小时前
高校后勤报修系统|物业管理|基于SprinBoot+vue的高校后勤报修系统(源码+数据库+文档)
java·前端·javascript·数据库·vue.js·毕设
朝新_8 小时前
【SpringMVC】SpringMVC 小案例:加法计算器初步理解前后端接口交互与数据处理
java·笔记·spring·交互·javaee