Ubuntu 22.04 Docker 安装与入门指南 – wiki基地


Ubuntu 22.04 Docker 安装与入门指南

前言:拥抱容器化时代

在现代软件开发和部署领域,容器化技术已经成为不可或缺的一部分。它提供了一种轻便、可移植且一致的环境来运行应用程序,极大地简化了“在我机器上能跑”到“在任何地方都能跑”的转化过程。而在众多容器技术中,Docker 无疑是最流行和最具影响力的。

Docker 允许开发者将应用程序及其所有依赖项打包到一个标准的单元中,称为“容器”。这个容器可以在任何支持 Docker 的环境中运行,而无需担心底层操作系统的差异或依赖库的冲突。这带来了巨大的便利性,无论是开发、测试还是生产环境。

Ubuntu 22.04 LTS(Jammy Jellyfish)是 Canonical 公司发布的长期支持版本,因其稳定性、安全性和广泛的应用而备受青睐。将强大的 Docker 与稳定的 Ubuntu 22.04 结合,是搭建高效、可靠的应用开发和部署环境的绝佳选择。

本篇文章将为你提供一个详细、全面的指南,涵盖如何在 Ubuntu 22.04 上安装 Docker Engine,并带领你迈出 Docker 入门的第一步,学习常用的 Docker 命令和概念。无论你是开发者、系统管理员还是对容器技术充满好奇的初学者,本指南都能帮助你顺利踏上 Docker 之旅。

我们将主要关注通过 Docker 官方仓库进行安装,这是获取最新版本和接收及时更新的最佳方式。

第一部分:安装 Docker Engine

在 Ubuntu 22.04 上安装 Docker Engine 有几种方法,但 Docker 官方推荐且最常用的方式是使用其官方 APT 仓库。这种方法可以确保你安装的是最新版本的 Docker,并且能够方便地进行后续更新。

1. 准备工作

在开始安装之前,请确保你的 Ubuntu 22.04 系统满足以下基本要求:

  • 操作系统: Ubuntu 22.04 LTS (Jammy Jellyfish) 64位系统。
  • 用户权限: 你需要一个拥有 sudo 权限的用户账户。安装 Docker 和后续管理操作通常需要管理员权限。
  • 网络连接: 确保你的服务器或虚拟机能够访问互联网,以便下载 Docker 安装包。

2. 卸载旧版本(如果存在)

如果你之前在系统上安装过 Docker 的旧版本(例如通过 Ubuntu 默认仓库安装的),建议先将其卸载干净,以避免潜在的冲突。请注意,卸载 Docker 并不会删除你的容器、镜像、卷或网络。

执行以下命令来卸载旧版本的 Docker 及其相关的包:

bash
sudo apt-get remove docker docker-engine docker.io containerd runc

  • docker docker-engine: 这些是 Docker 早期版本的主程序包名称。
  • docker.io: 这是 Ubuntu 默认仓库中提供的 Docker 包名称。
  • containerd: 这是 Docker 使用的容器运行时。
  • runc: 这是 OCI(Open Container Initiative)容器运行时的参考实现。

这条命令会尝试移除这些包,但如果它们不存在,系统会提示找不到,这属于正常情况。

3. 安装所需的依赖包

为了能够通过 HTTPS 连接到 Docker 的 APT 仓库并添加其 GPG 密钥,你需要安装一些必要的软件包:

bash
sudo apt-get update
sudo apt-get install \
ca-certificates \
curl \
gnupg \
lsb-release

  • sudo apt-get update: 更新你的本地软件包索引,确保你知道有哪些软件包及其最新版本。
  • ca-certificates: 允许 APT 通过 SSL/TLS 验证基于 HTTPS 的仓库证书。
  • curl: 一个命令行工具,用于传输数据,我们将用它来下载 Docker 的 GPG 密钥。
  • gnupg: GNU Privacy Guard,用于管理 GPG 密钥,我们将用它来验证下载的软件包的完整性和来源。
  • lsb-release: 这个包提供 lsb_release 命令,用于获取 Linux 发行版的信息,Docker 的仓库配置脚本会用到这些信息来确定适合你的仓库地址。

执行完这条命令后,系统会提示你确认安装这些包,输入 y 并回车即可。

4. 添加 Docker 的官方 GPG 密钥

Docker 使用 GPG 密钥来签署其软件包,以确保你下载的软件是 Docker 官方发布且未被篡改的。你需要将 Docker 的官方 GPG 公钥添加到你的系统,这样 APT 就能验证下载的 Docker 包的签名。

bash
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

  • sudo mkdir -p /etc/apt/keyrings: 创建一个目录 /etc/apt/keyrings,用于存放外部仓库的 GPG 密钥。-p 参数确保即使父目录不存在也会创建。
  • curl -fsSL https://download.docker.com/linux/ubuntu/gpg: 使用 curl 命令从 Docker 官方网站下载 GPG 密钥。
    • -f: 静默模式,不显示进度或错误信息。
    • -s: 静默模式,不显示错误信息。
    • -S: 如果发生错误,显示错误信息(与 -s 结合使用)。
    • -L: 如果遇到重定向,跟随重定向链接。
  • |: 管道符号,将 curl 的输出(GPG 密钥内容)作为输入传递给下一个命令。
  • sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg: 使用 gpg 命令将下载的 GPG 密钥进行解密并转换为适合 APT 使用的格式,然后保存到 /etc/apt/keyrings/docker.gpg 文件中。--dearmor 是将 GPG 密钥从 ASCII armored 格式转换为二进制格式。

执行这条命令后,不会有明显的输出,但 GPG 密钥文件应该已经成功保存在指定位置。

5. 添加 Docker 的 APT 仓库

现在,你需要将 Docker 的官方 APT 仓库添加到你的 Ubuntu 系统的软件源列表中。这样,APT 包管理器就知道去哪里查找和下载 Docker 软件包。

bash
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

  • echo "...": 打印仓库的配置字符串。
    • deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg]: 定义一个 debian 格式的仓库条目。
      • arch=$(dpkg --print-architecture): 自动检测你的系统架构(例如 amd64)。
      • signed-by=/etc/apt/keyrings/docker.gpg: 指定使用哪个 GPG 密钥文件来验证这个仓库中的软件包。
    • https://download.docker.com/linux/ubuntu: 这是 Docker 官方仓库的 URL。
    • $(lsb_release -cs): 自动检测你的 Ubuntu 版本代号(对于 22.04 来说是 jammy)。这将确保你获取的是对应版本分支的 Docker 包。
    • stable: 指定使用 stable 稳定版的仓库。你也可以选择 testnightly,但不推荐用于生产环境。
  • |: 管道符号,将 echo 的输出传递给下一个命令。
  • sudo tee /etc/apt/sources.list.d/docker.list: 使用 tee 命令将接收到的内容写入 /etc/apt/sources.list.d/docker.list 文件。tee 命令以管理员权限运行,同时也将内容输出到标准输出。
  • > /dev/null: 将 tee 命令输出到标准输出的内容重定向到 /dev/null,这样就不会在终端上看到重复的仓库信息。

执行这条命令后,你就成功地在 /etc/apt/sources.list.d/ 目录下创建了一个名为 docker.list 的文件,其中包含了 Docker 仓库的配置信息。

6. 更新 APT 软件包索引

在添加了新的仓库之后,你需要再次更新 APT 的软件包索引,以便它能够识别并加载 Docker 仓库中的软件包信息。

bash
sudo apt-get update

这次更新会比第一次多扫描 Docker 仓库,下载 Docker 相关的软件包列表。

7. 安装 Docker Engine、containerd 和 Docker Compose

现在,你可以通过 APT 安装 Docker Engine(docker-ce)、容器运行时(containerd.io)以及 Docker Compose CLI 工具(docker-compose-plugin)。Docker Compose 是用于定义和运行多容器 Docker 应用程序的工具,虽然不是 Docker Engine 本身,但通常与 Docker 一起安装和使用。

bash
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin

  • docker-ce: 这是 Docker Community Edition (CE) 的主程序包,包含 Docker Daemon。
  • docker-ce-cli: 这是 Docker 命令行客户端。你通过终端执行的 docker 命令就是由它提供的。
  • containerd.io: 这是 Docker 使用的符合 OCI 标准的容器运行时。
  • docker-compose-plugin: 这是新版本的 Docker Compose 安装方式,它作为一个 Docker CLI 的插件提供。

执行这条命令后,APT 会计算依赖关系并列出将要安装的软件包及其大小。仔细检查一下,确保它安装的是 docker-ce 等来自 Docker 官方仓库的包(通常版本号会比较新)。输入 y 并回车开始安装。

安装过程可能需要一些时间,取决于你的网络速度。

8. 验证安装

安装完成后,Docker 服务应该会自动启动。你可以运行一个简单的测试容器来验证 Docker Engine 是否正确安装并运行。hello-world 容器是一个非常小的镜像,它只是简单地打印一条消息然后退出。

bash
sudo docker run hello-world

执行这条命令时,Docker 会:
1. 检查本地是否有 hello-world 镜像。
2. 如果本地没有,它会从 Docker Hub(默认的镜像仓库)下载这个镜像。
3. 使用这个镜像创建一个新的容器并运行它。
4. 容器会输出一段祝贺信息,表明 Docker 安装成功。
5. 容器运行完毕后会自动停止。

如果一切正常,你会在终端上看到类似以下内容的输出:

“`
Unable to find image ‘hello-world:latest’ locally
latest: Pulling from library/hello-world
2db29710123e: Pull complete
Digest: sha256:…… # 省略具体的哈希值
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the “hello-world” image from the Docker Hub.
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/

For more examples and ideas, visit:
https://docs.docker.com/get-started/
“`

看到 “Hello from Docker!” 字样,就表示 Docker Engine 已经在你的 Ubuntu 22.04 系统上成功运行了!

你还可以检查 Docker 服务的状态:

bash
sudo systemctl status docker

输出应该显示 active (running),表明 Docker 服务正在运行。

9. 允许非 Root 用户使用 Docker (重要步骤!)

默认情况下,docker 命令需要 sudo 权限才能运行。这在日常使用中非常不便,而且频繁使用 sudo 也存在一定的安全风险。Docker 安装程序会创建一个名为 docker 的 Unix 组。将你的用户添加到这个组后,你就可以无需 sudo 即可运行 Docker 命令。

警告: docker 组授予的权限相当于 root 权限,因为组成员可以运行容器,而容器可以以 root 用户身份运行。考虑对你的系统安全产生的影响。

将当前用户添加到 docker 组:

bash
sudo usermod -aG docker $USER

  • sudo usermod: 修改用户账户的命令。
  • -aG: -a 表示追加,-G 表示指定要加入的组。这两个选项结合使用,表示将用户追加到指定的组,而不是替换用户现有的组。
  • docker: 要加入的组的名称。
  • $USER: 这是一个环境变量,代表当前登录的用户名。

执行完此命令后,更改不会立即生效,直到你退出当前终端会话并重新登录,或者执行 newgrp docker 命令。建议直接退出终端(或 SSH 会话)并重新登录,这是最可靠的方式。

重新登录后,尝试再次运行 hello-world,这次不带 sudo

bash
docker run hello-world

如果不再提示权限错误并且输出了 “Hello from Docker!”,说明你已经可以作为非 root 用户使用 Docker 了。

10. 配置 Docker 开机自启动

Docker 服务在安装时通常会被配置为开机自启动。你可以通过以下命令确认并启用它:

bash
sudo systemctl enable docker

这条命令会创建一个符号链接,确保在系统启动时启动 Docker 服务。

至此,Docker Engine 已经在你的 Ubuntu 22.04 系统上成功安装并配置完成,你可以开始使用 Docker 了!

第二部分:Docker 入门基础

安装好了 Docker,是时候了解一些核心概念和常用命令,开始你的容器化之旅了。

1. Docker 核心概念

在深入学习命令之前,理解 Docker 的几个核心概念非常重要:

  • 镜像 (Image): Docker 镜像是用于创建 Docker 容器的只读模板。一个镜像可以包含一个操作系统(通常是精简版)、应用程序代码、运行时、库、环境变量和配置文件等。镜像通过 Dockerfile 定义,可以从 Docker Hub 或其他容器仓库中获取,也可以自己构建。镜像具有层次结构,基于一个基础镜像层层构建。

    • 类比: 镜像就像是面向对象编程中的“类”或者虚拟机的“模板文件”。
  • 容器 (Container): Docker 容器是镜像的一个运行实例。容器是 Docker 的执行单元。每个容器都是相互隔离的,拥有自己的文件系统、网络接口、进程空间等,但是它们共享同一个宿主机的操作系统内核。你可以启动、停止、删除、创建容器。

    • 类比: 容器就像是面向对象编程中的“对象”或者运行中的“虚拟机实例”。
  • Dockerfile: Dockerfile 是一个文本文件,包含了一系列用于构建 Docker 镜像的指令。通过 Dockerfile,你可以自动化镜像的创建过程,实现可重复和版本化的镜像构建。

    • 类比: Dockerfile 就像是构建镜像的“脚本”或“菜谱”。
  • 仓库 (Registry): Docker 仓库是存放 Docker 镜像的地方。最著名的公共仓库是 Docker Hub(hub.docker.com)。你也可以搭建私有的 Docker 仓库。通过仓库,你可以分享、存储和管理 Docker 镜像。

    • 类比: 仓库就像是代码的“GitHub”或软件包的“APT 仓库”。
  • 卷 (Volume): 容器在运行时产生的数据默认存储在容器的可写层。当容器被删除时,这些数据也会丢失。卷是一种用于持久化容器数据的方式,它独立于容器的生命周期存在于宿主机的文件系统上。

    • 类比: 卷就像是外部连接到容器的“数据盘”。
  • 网络 (Network): Docker 提供了多种网络模式,用于连接不同的容器以及容器与外部世界。容器可以连接到同一个网络,以便相互通信,也可以通过端口映射暴露服务给宿主机或外部网络。

2. 常用的 Docker CLI 命令

以下是一些最常用的 Docker 命令行接口 (CLI) 命令:

  • docker pull [镜像名称[:标签]]:

    • 作用:从仓库中下载一个或多个镜像。
    • 示例:docker pull ubuntu:22.04 下载 Ubuntu 22.04 镜像;docker pull nginx 下载最新版的 Nginx 镜像(默认使用 latest 标签)。
    • 如果只指定镜像名称而不指定标签,默认会尝试下载 latest 标签的镜像。
  • docker images:

    • 作用:列出本地系统中已经下载的 Docker 镜像。
    • 输出:显示镜像的仓库名、标签、镜像 ID、创建时间和大小。
  • docker run [选项] 镜像名称[:标签] [命令] [参数]:

    • 作用:使用指定的镜像创建一个新的容器并运行它。这是最核心的命令之一,有很多重要的选项。
    • 常用选项:
      • -it: 以交互模式运行容器,并分配一个伪终端。常用于需要进入容器执行命令的场景(如 docker run -it ubuntu bash)。
      • -d: 在后台(分离模式)运行容器,并打印新的容器 ID。
      • -p <宿主机端口>:<容器端口>: 将容器内部的端口映射到宿主机的端口,以便外部可以访问容器提供的服务。可以指定多个 -p
      • -v <宿主机路径>:<容器路径>: 将宿主机的路径或命名卷挂载到容器内部的指定路径,用于数据持久化或共享。
      • --name <容器名称>: 为容器指定一个名称,方便管理(否则 Docker 会随机生成一个名称)。
      • --rm: 容器停止后自动删除容器实例。
      • --network <网络名称>: 指定容器连接到哪个 Docker 网络。
    • 示例:docker run -d -p 80:80 --name mynginx nginx 在后台运行一个 Nginx 容器,将宿主机的 80 端口映射到容器的 80 端口,并命名为 mynginx
  • docker ps:

    • 作用:列出当前正在运行的容器。
    • 输出:显示容器 ID、使用的镜像、运行的命令、创建时间、状态、端口映射和容器名称。
    • docker ps -a: 列出所有容器,包括正在运行和已停止的。
  • docker stop <容器 ID 或名称>:

    • 作用:停止一个正在运行的容器。
    • 示例:docker stop mynginxdocker stop a3f1...
  • docker start <容器 ID 或名称>:

    • 作用:启动一个已停止的容器。
    • 示例:docker start mynginx
  • docker restart <容器 ID 或名称>:

    • 作用:重启一个容器。
  • docker rm <容器 ID 或名称>:

    • 作用:删除一个已停止的容器。要删除正在运行的容器,可以使用 -f 选项 (docker rm -f <容器 ID 或名称>),但这会强制停止并删除。
  • docker rmi <镜像 ID 或名称[:标签]>:

    • 作用:删除一个或多个本地镜像。如果某个镜像正在被容器使用,需要先删除使用它的容器才能删除镜像。
    • 示例:docker rmi ubuntu:22.04docker rmi f70734b6a266
  • docker exec [选项] <容器 ID 或名称> <命令> [参数]:

    • 作用:在运行中的容器内部执行一条命令。
    • 常用选项:-it 用于需要交互的命令(如进入容器的 shell)。
    • 示例:docker exec -it mynginx bash 在名为 mynginx 的容器中启动一个 bash shell。
  • docker logs <容器 ID 或名称>:

    • 作用:查看容器的标准输出和标准错误日志。
    • 示例:docker logs mynginx
  • docker build [选项] <Dockerfile 路径>:

    • 作用:根据 Dockerfile 构建一个新的镜像。通常在 Dockerfile 所在的目录下执行 docker build . (点代表当前目录)。
    • 常用选项:-t <镜像名称[:标签]> 为构建的镜像指定名称和标签。
    • 示例:docker build -t myapp:1.0 .
  • docker login:

    • 作用:登录到 Docker 仓库(如 Docker Hub)。
    • 示例:docker login 会提示输入用户名和密码。
  • docker logout:

    • 作用:登出 Docker 仓库。

3. 简单实战:运行一个 Nginx Web 服务器

让我们通过一个简单的例子来巩固上面学到的命令:运行一个 Nginx Web 服务器容器。

步骤 1:拉取 Nginx 镜像

首先,我们需要从 Docker Hub 下载 Nginx 的官方镜像。

bash
docker pull nginx

Docker 会显示下载进度。下载完成后,你可以用 docker images 命令查看:

bash
docker images

你会看到类似这样的输出:

REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest abcdef123456 2 weeks ago 133MB
hello-world latest ....... ...... ......

步骤 2:运行 Nginx 容器

现在,使用 nginx 镜像创建一个新的容器并运行它。我们将使用 -d 在后台运行,并使用 -p 将宿主机的 80 端口映射到容器内部 Nginx 默认监听的 80 端口,并给容器起一个友好的名字 my-nginx-server

bash
docker run -d -p 80:80 --name my-nginx-server nginx

执行命令后,你会看到一串容器的 ID。

步骤 3:检查容器状态

使用 docker ps 命令查看正在运行的容器:

bash
docker ps

输出应该包含 my-nginx-server 这个容器,状态是 Up (运行中),并且显示端口映射是 0.0.0.0:80->80/tcp

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a3f1b2c4d5e6 nginx "/docker-entrypoint.…" 1 minute ago Up 1 minute 0.0.0.0:80->80/tcp, :::80->80/tcp my-nginx-server

步骤 4:访问 Nginx 服务器

如果你的 Ubuntu 系统有公共 IP 地址,你可以通过浏览器访问该 IP 地址。如果是在本地虚拟机或服务器上,你可以通过 localhost 或系统的局域网 IP 地址访问。

在浏览器中打开 http://localhosthttp://<你的服务器IP>。你应该能看到 Nginx 的欢迎页面(”Welcome to nginx!”)。

如果你在命令行界面,可以使用 curl 命令测试:

bash
curl http://localhost

或者如果 Docker 运行在远程服务器上,你需要从能访问该服务器的机器上执行 curl http://<服务器IP>

步骤 5:查看容器日志 (可选)

你可以使用 docker logs 命令查看 Nginx 容器的访问日志和错误日志:

bash
docker logs my-nginx-server

步骤 6:停止和删除容器

当你不再需要这个容器时,应该停止并删除它,以释放资源。

首先停止容器:

bash
docker stop my-nginx-server

使用 docker ps 检查,会发现容器已经不在运行列表中了。使用 docker ps -a 可以看到它处于 Exited 状态。

然后删除容器:

bash
docker rm my-nginx-server

使用 docker ps -a 检查,会发现容器已经被移除了。

如果你想删除下载的 Nginx 镜像,可以使用 docker rmi nginx 命令。但前提是没有容器正在使用它。

这个简单的例子展示了拉取镜像、运行容器、端口映射以及停止/删除容器的基本流程。

4. 进一步探索:Dockerfile 和构建自定义镜像

虽然使用现成的镜像很方便,但在实际应用中,你经常需要打包自己的应用程序。这就需要用到 Dockerfile。

Dockerfile 是一个简单的文本文件,其中包含了一系列指令。Docker 读取这些指令,并按顺序执行它们来构建一个镜像。

以下是一个非常简单的 Dockerfile 示例,用于构建一个包含一个简单 HTML 文件的 Nginx 镜像:

  1. 创建一个新的目录用于存放 Dockerfile 和你的文件:

    bash
    mkdir my-custom-nginx
    cd my-custom-nginx

  2. 创建一个简单的 HTML 文件 (index.html):

    bash
    echo "<h1>Hello from my custom Nginx container!</h1>" > index.html

  3. 创建一个名为 Dockerfile 的文件 (注意文件名大小写敏感,没有扩展名):

    bash
    nano Dockerfile

    在文件中输入以下内容:

    “`dockerfile

    使用官方 Nginx 镜像作为基础镜像

    FROM nginx:latest

    将本地的 index.html 文件复制到容器中 Nginx 的默认发布目录

    COPY index.html /usr/share/nginx/html/
    “`

    • FROM nginx:latest: 指定使用哪个已有的镜像作为新镜像的基础。这里使用最新的官方 Nginx 镜像。
    • COPY index.html /usr/share/nginx/html/: 将构建上下文目录(即 Dockerfile 所在的目录)中的 index.html 文件复制到镜像文件系统中 Nginx 的默认网页发布目录 /usr/share/nginx/html/
  4. 保存并关闭 Dockerfile

  5. 构建镜像:在 my-custom-nginx 目录下执行构建命令,并为新镜像命名:

    bash
    docker build -t my-custom-nginx:1.0 .

    • docker build: 构建镜像的命令。
    • -t my-custom-nginx:1.0: 为构建的镜像指定名称 (my-custom-nginx) 和标签 (1.0)。
    • .: 指定构建上下文路径。. 表示当前目录,Docker 会将当前目录下的所有文件(包括 Dockerfile 和 index.html)发送给 Docker Daemon 进行构建。

    Docker 会显示构建过程的输出,包括每个步骤的执行情况。

  6. 运行自定义镜像的容器

    bash
    docker run -d -p 8080:80 --name custom-nginx-server my-custom-nginx:1.0

    这次我们将宿主机的 8080 端口映射到容器的 80 端口,以免与之前可能的 Nginx 容器冲突。

  7. 验证:在浏览器中访问 http://localhost:8080http://<你的服务器IP>:8080。你应该能看到 index.html 中的内容:”Hello from my custom Nginx container!”。

通过 Dockerfile,你可以轻松地将你的应用程序代码、配置和其他文件打包到自定义镜像中,实现应用环境的标准化和自动化部署。

5. 数据持久化:使用 Docker Volumes

容器是短暂的,它们的数据存储在容器的可写层,随容器的删除而消失。为了持久化数据,我们需要使用 Docker Volumes。

使用 -v 选项可以在运行容器时挂载卷。

示例:持久化 Nginx 的网页内容

假设我们想将 Nginx 容器的网页发布目录 /usr/share/nginx/html 挂载到宿主机的一个目录,这样即使容器被删除,我们的网页文件也不会丢失,并且可以直接在宿主机上编辑文件。

  1. 在宿主机上创建存放网页文件的目录

    bash
    mkdir ~/nginx-html
    echo "<h1>This is a persistent page!</h1>" > ~/nginx-html/index.html

  2. 运行 Nginx 容器并挂载卷

    bash
    docker run -d -p 8081:80 --name persistent-nginx -v ~/nginx-html:/usr/share/nginx/html nginx

    • -v ~/nginx-html:/usr/share/nginx/html: 将宿主机的 ~/nginx-html 目录挂载到容器内部的 /usr/share/nginx/html 目录。冒号前面是宿主机路径,后面是容器路径。
  3. 验证:访问 http://localhost:8081。你应该看到 “This is a persistent page!”。

  4. 修改宿主机文件:编辑 ~/nginx-html/index.html 文件,修改内容。

    bash
    echo "<h1>Content updated persistently!</h1>" > ~/nginx-html/index.html

  5. 刷新浏览器:再次访问 http://localhost:8081,你会看到网页内容已经更新。这证明容器正在使用宿主机上的文件。

  6. 停止并删除容器

    bash
    docker stop persistent-nginx
    docker rm persistent-nginx

  7. 验证数据持久性:虽然容器已经被删除,但宿主机上的 ~/nginx-html 目录及其内容仍然存在。当你下次创建新的 Nginx 容器并挂载同一个目录时,它将继续使用这些文件。

除了绑定挂载(Bind Mounts,如上面示例将宿主机目录挂载到容器),Docker 还提供了命名卷(Named Volumes),它们由 Docker 管理,存储在宿主机上的特定位置。命名卷通常是更推荐的数据持久化方式,因为它更易于管理,并且 Docker 会处理卷的创建和生命周期。

要使用命名卷:

  1. 创建一个命名卷

    bash
    docker volume create my-nginx-data

  2. 运行容器并使用命名卷

    bash
    docker run -d -p 8082:80 --name volume-nginx -v my-nginx-data:/usr/share/nginx/html nginx

    • -v my-nginx-data:/usr/share/nginx/html: 冒号前面是命名卷的名称,后面是容器路径。第一次运行时,如果命名卷不存在会自动创建。如果命名卷是空的,Docker 会将容器路径下的初始内容复制到卷中。
  3. 验证:访问 http://localhost:8082,首次会看到 Nginx 默认页面。

  4. 进入容器修改文件 (演示)

    bash
    docker exec -it volume-nginx bash
    echo "<h1>Content from volume!</h1>" > /usr/share/nginx/html/index.html
    exit

  5. 刷新浏览器:再次访问 http://localhost:8082,会看到更新后的内容。

  6. 停止并删除容器

    bash
    docker stop volume-nginx
    docker rm volume-nginx

  7. 再次运行一个新容器使用同一个命名卷

    bash
    docker run -d -p 8083:80 --name volume-nginx-2 -v my-nginx-data:/usr/share/nginx/html nginx

  8. 验证:访问 http://localhost:8083,你会直接看到 “Content from volume!”,证明数据在命名卷中持久化了。

命名卷的实际数据存储位置可以在 docker volume inspect my-nginx-data 的输出中查看。

第三部分:故障排除和常见问题

在安装或使用 Docker 过程中,可能会遇到一些问题。以下是一些常见问题及其解决方案:

  • docker: command not foundGot permission denied while trying to connect to the Docker daemon socket...

    • 原因: 用户没有执行 Docker 命令的权限。这通常是因为当前用户不在 docker 组中,或者虽然加入了但更改未生效。
    • 解决方案:
      1. 确认你已经执行了 sudo usermod -aG docker $USER 命令。
      2. 最重要的是: 退出当前的终端会话(如果是 SSH 连接,断开并重新连接)并重新登录。或者尝试运行 newgrp docker(虽然重新登录更可靠)。
      3. 执行 groups 命令,确认 docker 组是否在你的用户组列表中。
      4. 如果问题依然存在,尝试重启 Docker 服务 (sudo systemctl restart docker) 或重启整个系统。
  • Unable to find image 'some-image:latest' locally

    • 原因: Docker 找不到指定的镜像。
    • 解决方案:
      1. 检查镜像名称和标签是否拼写正确。
      2. 确认你的系统能够访问互联网和 Docker Hub(或你指定的仓库)。尝试 ping hub.docker.com 或执行 docker pull some-image 手动拉取。
      3. 检查 Docker Daemon 是否正在运行 (sudo systemctl status docker)。
  • 容器启动失败或立即退出

    • 原因: 可能有多种原因,例如容器内部应用程序配置错误、端口冲突、缺少依赖、命令错误等。
    • 解决方案:
      1. 使用 docker ps -a 查看所有容器,包括已退出的,找到你的容器 ID 或名称。
      2. 使用 docker logs <容器 ID 或名称> 查看容器的启动日志和错误信息。日志通常能揭示失败的具体原因。
      3. 如果容器因为命令错误或应用程序崩溃而退出,日志会非常有帮助。
      4. 检查容器的端口映射是否与宿主机上已占用的端口冲突。
      5. 尝试以交互模式运行容器 (docker run -it <镜像名称> bash) 进入容器内部,手动执行启动命令或检查文件,以便调试。
  • 无法访问容器暴露的服务(端口映射问题)

    • 原因: 端口映射配置错误、宿主机防火墙阻止访问、容器内部服务未监听正确端口或地址。
    • 解决方案:
      1. 检查 docker ps 输出中的 PORTS 列,确认端口映射是否正确 (宿主机端口->容器端口)。
      2. 确认容器内部的服务正在监听指定的端口。可以通过 docker exec <容器 ID> netstat -tulnp (如果容器内有 netstat 命令) 或查看应用日志来确认。
      3. 检查宿主机的防火墙(如 ufwfirewalld)是否允许外部访问映射的宿主机端口。例如,如果使用 ufw,需要允许对应的端口 (sudo ufw allow <端口号>)。
      4. 如果 Docker Daemon 是通过 systemd socket 激活的,Docker 可能会在防火墙规则中加入例外。但手动配置防火墙规则依然是常见需求。
  • 存储空间不足

    • 原因: Docker 镜像和容器会占用磁盘空间,特别是当你拉取大量镜像或运行很多容器后。
    • 解决方案:
      1. 使用 docker system df 命令查看 Docker 占用的磁盘空间。
      2. 使用 docker image prune 删除所有悬空镜像(没有被任何标签引用的镜像)。
      3. 使用 docker container prune 删除所有已停止的容器。
      4. 使用 docker volume prune 删除所有未被容器使用的命名卷。
      5. 使用 docker builder prune 清理构建缓存。
      6. docker system prune 可以清理所有停止的容器、网络、悬空镜像和构建缓存(使用 -a 可以清理所有未使用的镜像,而不仅仅是悬空镜像)。注意: docker system prune 命令会删除很多东西,请谨慎使用,并理解其影响。

结论

恭喜你!你已经成功在 Ubuntu 22.04 上安装了 Docker Engine,并学习了 Docker 的核心概念和常用命令,甚至构建了你的第一个自定义镜像并学会了如何持久化数据。

Docker 是一个功能强大且用途广泛的工具,它彻底改变了软件的打包、分发和运行方式。通过本指南,你已经掌握了 Docker 的基本操作,这为你进一步深入学习 Docker 生态系统打下了坚实的基础。

接下来,你可以继续探索 Docker Compose 来管理多个相关的容器应用、学习如何编写更复杂的 Dockerfile 来优化镜像构建、深入研究 Docker 网络和安全、了解 Docker Swarm 或 Kubernetes 等容器编排工具。

容器化的世界充满无限可能,不断实践和学习是掌握 Docker 的最佳途径。现在就开始用 Docker 构建和运行你的应用程序吧!祝你在 Docker 的旅途中一切顺利!


发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部