本文补充了关于在云中部署和管理容器化工作负载的 网络研讨会系列 。 该系列涵盖了容器的基本知识,包括容器生命周期管理、部署多容器应用程序、扩展工作负载和理解 Kubernetes,并重点介绍了运行有状态应用程序的最佳实践。
本教程包括该系列的第一个会话“容器入门”中介绍的概念和命令。
介绍
Docker 是一个部署和管理容器化应用程序的平台。 由于容器提供的灵活性,容器在开发人员、管理员和 devops 工程师中很受欢迎。
Docker 具有三个基本组件:
- 码头引擎
- 码头工人工具
- Docker 注册表
Docker Engine 提供了管理容器的核心能力。 它与底层 Linux 操作系统交互,以公开简单的 API 来处理容器的生命周期。
Docker 工具是一组命令行工具,与 Docker 引擎公开的 API 对话。 它们用于运行容器、创建新映像、配置存储和网络,以及执行更多影响容器生命周期的操作。
Docker Registry 是存储容器镜像的地方。 每个图像可以具有通过唯一标签标识的多个版本。 用户从注册表中提取现有图像并将新图像推送到它。 Docker Hub 是由 Docker, Inc. 管理的托管注册表。也可以在您自己的环境中运行注册表以使图像更接近引擎。
在本教程结束时,您将在 DigitalOcean Droplet 上安装 Docker、托管容器、处理图像、添加持久性并设置私有注册表。
先决条件
要遵循本教程,您将需要:
- 按照本 Ubuntu 16.04 初始服务器设置教程 设置一个 Ubuntu 16.04 Droplet,包括 sudo 非 root 用户和防火墙。
- 一个 Docker Hub 帐户。 Docker Hub概述将帮助您入门。
默认情况下,docker
命令需要 root 权限。 但是,您可以通过以 docker 组中的用户身份运行 docker
来执行不带 sudo
前缀的命令。
要以这种方式配置您的 Droplet,请运行命令 sudo usermod -aG docker ${USER}
。 这会将当前用户添加到 docker
组。 然后,运行命令 su - ${USER}
以应用新的组成员身份。
本教程要求您的服务器配置为运行不带 sudo
前缀的 docker
命令。
第 1 步 — 安装 Docker
在通过 SSH 连接到 Droplet 后,运行以下命令以删除任何可能已经安装的现有 docker 相关包,然后从官方存储库安装 Docker:
sudo apt-get remove docker docker-engine docker.io sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - sudo apt-key fingerprint 0EBFCD88 sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" sudo apt-get update sudo apt-get install -y docker-ce
安装 Docker 后,使用以下命令验证安装:
docker info
上述命令显示了环境中部署的 Docker Engine 的详细信息。 下一条命令验证 Docker 工具是否已正确安装和配置。 它应该打印 Docker Engine 和 Tools 的版本。
docker version
- Step 2 — 启动容器
Docker 容器是从存储在注册表中的现有图像启动的。 Docker 中的图像可以存储在私有或公共存储库中。 私有存储库要求用户在提取图像之前进行身份验证。 任何人都可以访问公共图像。
要搜索名为 hello-world
的图像,请运行以下命令:
docker search hello-world
可能有多个图像与名称 hello-world
匹配。 选择星星最多的那一个,这表明图像的受欢迎程度。
使用以下命令检查本地环境中的可用映像:
docker images
由于我们还没有启动任何容器,所以不会有任何图像。 我们现在可以下载镜像并在本地运行它:
docker pull hello-world docker run hello-world
如果我们在不拉取镜像的情况下执行docker run
命令,Docker Engine会先拉取镜像然后运行。 再次运行 docker images
命令表明我们在本地有可用的 hello-world
图像。
让我们启动一个更有意义的容器:一个 Apache Web 服务器。
docker run -p 80:80 --name web -d httpd
您可能会注意到传递给 docker run
命令的其他选项。 下面是对这些开关的解释:
-p
- 这告诉 Docker 引擎在主机的端口80
上公开容器的端口80
。 由于 Apache 侦听端口80
,因此我们需要在主机端口上公开它。--name
- 此开关为我们正在运行的容器分配一个名称。 如果我们忽略它,Docker 引擎将分配一个随机名称。-d
- 此选项指示 Docker 引擎以分离模式运行容器。 没有这个,容器将在前台启动,阻止对 shell 的访问。 通过将容器推入后台,我们可以在容器仍在运行时继续使用 shell。
要验证我们的容器确实在后台运行,请尝试以下命令:
docker ps
输出显示名为 web
的容器正在运行,端口 80
映射到主机端口 80
。
现在访问网络服务器:
curl localhost
让我们使用以下命令停止并删除正在运行的容器:
docker stop web docker rm web
再次运行 docker ps
确认容器已终止。
第 3 步 — 向容器添加存储
容器是短暂的,这意味着容器中存储的任何内容都会在容器终止时丢失。 为了在容器的生命周期之外持久保存数据,我们需要将一个卷附加到容器。 卷是来自主机文件系统的目录。
首先在主机上创建一个新目录:
mkdir htdocs
现在,让我们使用新开关启动容器以挂载 htdocs
目录,将其指向 Apache Web 服务器的文档根目录:
docker run -p 80:80 --name web -d -v $PWD/htdocs:/usr/local/apache2/htdocs httpd
-v
开关将容器内的 htdocs
目录指向主机的文件系统。 对此目录所做的任何更改都将在这两个位置可见。
通过运行以下命令从容器访问目录:
docker exec -it web /bin/bash
此命令以交互模式将我们的终端附加到容器的外壳。 您应该看到您现在被放入容器中。
导航到 htdocs
文件夹并创建一个简单的 HTML 文件。 最后退出shell返回宿主机:
cd /usr/local/apache2/htdocs echo '<h1>Hello World from Container</h1>' > index.html exit
再次执行 curl localhost
命令显示 Web 服务器正在返回我们创建的页面。
我们不仅可以从主机访问这个文件,还可以修改它:
cd htdocs cat index.html echo '<h1>Hello World from Host</h1>' | sudo tee index.html >/dev/null
再次运行 curl localhost
确认 Web 服务器正在提供从主机创建的最新页面。
使用以下命令终止容器。 (-f
强制 Docker 不先停止就终止。)
docker rm -f web
第 4 步 — 构建图像
除了从注册表运行现有图像外,我们还可以创建自己的图像并将它们存储在注册表中。
您可以从现有容器创建新图像。 首先提交对容器所做的更改,然后标记图像并将其推送到注册表。
让我们再次启动 httpd
容器并修改默认文档:
docker run -p 80:80 --name web -d httpd docker exec -it web /bin/bash cd htdocs echo '<h1>Welcome to my Web Application</h1>' > index.html exit
容器现在使用自定义的 index.html
运行。 您可以使用 curl localhost
进行验证。
在我们提交更改的容器之前,最好停止它。 停止后,我们将运行 commit 命令:
docker stop web docker commit web doweb
使用 docker images
命令确认图像的创建。 它显示了我们刚刚创建的 doweb
图像。
要在 Docker Hub 中标记和存储此映像,请运行以下命令将您的映像推送到公共注册表:
docker login docker tag your_docker_hub_username/doweb docker push your_docker_hub_username/doweb
您可以通过从浏览器或命令行在 Docker Hub 中搜索来验证新映像。
第 5 步 — 启动私有注册表
可以在私有环境中运行注册表以保持图像更安全。 它还减少了 Docker 引擎和图像存储库之间的延迟。
Docker Registry 作为一个容器提供,可以像任何其他容器一样启动。 由于注册表包含多个图像,因此最好将存储卷附加到它。
docker run -d -p 5000:5000 --restart=always --name registry -v $PWD/registry:/var/lib/registry registry
请注意,容器在后台启动,端口 5000
暴露,并且 registry
目录映射到主机文件系统。 您可以通过执行 docker ps
命令来验证容器是否正在运行。
我们现在可以标记本地图像并将其推送到私有注册表。 让我们首先从 Docker Hub 中拉出 busybox
容器并标记它。
docker pull busybox docker tag busybox localhost:5000/busybox docker images
前面的命令确认 busybox
容器现在标记为 localhost:5000
,因此将映像推送到私有注册表。
docker push localhost:5000/busybox
将映像推送到本地注册表后,让我们尝试将其从环境中删除并从注册表中拉回。
docker rmi -f localhost:5000/busybox docker images docker pull localhost:5000/busybox docker images
我们经历了拉动图像、标记图像、将其推送到本地注册表,最后将其拉回的完整循环。
在某些情况下,您可能希望在专用主机中运行私有注册表。 在不同机器上运行的 Docker 引擎将与远程注册表对话以拉取和推送图像。
由于注册表不安全,我们需要修改 Docker Engine 的配置以启用对不安全注册表的访问。 为此,请编辑位于 /etc/docker/daemon.json
的 daemon.json
文件。 如果文件不存在,则创建该文件。
添加以下条目:
编辑 /etc/docker/daemon.json
{ "insecure-registries" : ["REMOTE_REGISTRY_HOST:5000"] }
将 REMOTE_REGISTRY_HOST
替换为远程注册表的主机名或 IP 地址。 重新启动 Docker Engine 以确保应用配置更改。
- Conclusion 本教程帮助您开始使用 Docker。 它涵盖了基本概念,包括安装、容器管理、映像管理、存储和私有注册表。 本系列中即将到来的会议和文章将帮助您超越Docker的基础知识。