介绍

Docker Registry(Docker注册中心)是一个管理Docker容器镜像存储和交付的应用程序。注册中心集中容器镜像并减少开发人员的构建时间。Docker镜像通过虚拟化保证相同的运行环境,但是构建镜像需要大量的时间投入。例如,开发人员可以从包含所有必要组件的注册中心下载压缩镜像,而不是单独安装依赖项和包来使用Docker。此外,开发人员可以使用持续集成工具,例如:Buddy自动将镜像推送到注册中心,以在生产和开发过程中无缝更新镜像。

Docker Hub是一个免费公共的注册中心,可以托管您的自定义Docker镜像,但在某些情况下您不希望您的镜像公开使用。镜像通常包含运行应用程序所需的所有代码,因此在使用专有软件时最好使用私有的注册中心。

通过本文您将学到以下的大致内容:

  • Ubuntu 22.04初始服务器设置指南
  • 如何在Ubuntu 22.04上安装和使用Docker
  • 如何在Ubuntu 22.04上安装和使用Docker Compose
  • 如何在Ubuntu 22.04上安装Nginx
  • 如何在Ubuntu 22.04上使用Let's Encrypt安全地使用Nginx
  • 如何在Ubuntu 22.04上设置私有Docker注册中心
  • DevOps开发运维一体化与Docker完美结合

初始服务器设置

首次新建Ubuntu 22.04服务器时,您应该执行一些重要的配置步骤作为初始设置的一部分。这些步骤将提高服务器的安全性和可用性,并为您的后续操作打下坚实的基础。

登录为root

要登录到您的服务器,您需要知道服务器的公网IP地址。您还需要root用户帐户密码或密钥(如果您安装了用于身份验证的SSH密钥)。

如果当前未连接到您的服务器,请使用以下命令以root用户身份登录。将命令中您的_公网_IP部分替换为您服务器的公网IP地址:

ssh root@您的_公网_IP

接受有关主机显示的提示(如果出现)。如果您的服务器使用密码身份验证,请提供您的root密码以登录。如果您使用受密码保护的SSH密钥,您可能需要在每次会话首次使用该密钥时输入密码如果这是您第一次使用密码登录服务器,您可能还需要更改root密码。 如果收到提示,请按照说明更改密码即可。

关于root

root用户是Linux环境中具有提升权限的管理用户。由于root帐户具有更高的权限,因此不鼓励您经常使用root。root帐户可以做出非常具有破坏性的更改,即使是意外的操作也可能带来很大的破坏。

下一步是设置一个新的用户帐户,降低日常使用的权限。稍后,我们将向您展示如何在您需要时临时获得更高的权限。

新建用户

以root身份登录后,您将能够添加新的用户帐户。 将来,我们将使用这个新帐户而不是root登录。

此示例创建一个名为edal的新用户,但您应该将其替换为您喜欢的用户名:

adduser edal

您将被要求回答一些问题,首先是帐户密码。

输入一个强悍的密码,如果需要的话,填写任何附加信息。这些信息不是必需的,您可以在任何您想跳过的字段中按回车键。

授予管理员权限

现在您拥有一个具有普通帐户权限的新用户帐户。然而,您有时需要以root用户身份执行管理任务。

为了避免注销您的常规用户并重新登录root帐户,您可以为用户的常规帐户设置所谓的超级用户roo权限。这些权限将允许您的普通用户在命令前加上sudo以使用管理权限运行命令。

要将这些权限添加到您的新用户中,您需要将用户添加到sudo系统组中。在Ubuntu 22.04上,默认情况下属于sudo组的用户可以使用sudo命令。

以root身份运行此命令将您的新用户添加到sudo组中:

usermod -aG sudo edal

您现在可以在命令前键入sudo,以在以普通用户身份登录时以超级用户权限运行。

设置防火墙

Ubuntu 22.04服务器可以使用UFW防火墙来确保只允许连接到某些服务。 您可以使用此应用程序设置基本防火墙。

应用程序可以在安装时向UFW注册它们的配置文件。这些配置文件允许UFW按名称管理这些应用程序。OpenSSH,允许您连接到您的服务器的服务,有一个在UFW注册的配置文件。

您可以通过键入以下内容来检查已安装的UFW配置文件列表:

ufw app list
输出信息
Available applications:
  OpenSSH

您需要确保防火墙允许SSH连接,以便您下次可以登录到您的服务器。通过键入以下内容允许这些连接:

ufw allow OpenSSH

然后输入以下命令启用防火墙

ufw enable

输入y并按回车键继续。您可以通过键入以下内容看到仍然允许SSH连接:

ufw status
输出信息
Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)

防火墙当前阻止除SSH之外的所有连接。如果您安装和配置附加服务,您将需要调整防火墙设置以允许新流量进入您的服务器。

为普通用户启用外部访问

现在您已经有了日常使用的普通用户,您需要确保可以通过SSH直接连接到该帐户。

为新用户配置SSH访问取决于您服务器的根帐户是使用密码还是SSH密钥进行身份验证。

如果root账户使用密码认证

如果您使用密码登录到您的root帐户,则会为SSH启用密码身份验证。您可以通过打开一个新的终端会话并使用SSH和您的新用户名连SSH到您的新用户帐户:

sudo command_to_run

如果root账户使用SSH密钥认证

如果您使用SSH密钥登录到您的根帐户,则SSH的密码身份验证将被禁用。要使用SSH密钥以普通用户身份登录,您必须将本地公钥的副本添加到新用户的 ~/.ssh/authorized_keys 文件中。

由于您的公钥已经在服务器上根帐户的 ~/.ssh/authorized_keys 文件中,您可以使用当前会话将该文件和目录结构复制到新用户帐户。

复制具有正确所有权和权限的文件的最简单方法是使用rsync命令。此命令将复制root用户的.ssh目录、保留权限并修改文件所有者,所有这些都在一个命令中完成。确保更改相关命令以匹配您的常规用户名:

rsync命令处理以斜杠结尾与没有斜杠不同在下面使用rsync时,请确保源目录(~/.ssh)不包含尾部斜杠(检查以确保您没有使用 ~/.ssh/)。

如果您不小心在命令中添加斜杠结尾,rsync会将root帐户的 ~/.ssh 目录的内容复制到sudo用户的主目录,而不是复制整个 ~/.ssh 目录结构。 若如此文件将位于错误的位置,SSH将无法找到和使用。

rsync --archive --chown=edal:edal ~/.ssh /home/edal

现在,在你的本地机器上打开一个新的终端会话,并使对新用户名使用SSH:

ssh edal@your_server_ip

您就能使用新用户帐户连接到服务器而无需使用密码。 请记住,如果您需要以管理权限运行命令,请在命令前键入sudo,如下所示:

sudo 加上命令

每次会话首次使用sudo时(之后会定期提示),系统都会提示您输入普通用户的密码。

安装和使用Docker

安装Docker

官方Ubuntu存储仓中提供的Docker安装包可能不是最新版本。为确保获得最新版本,我们将从官方Docker存储仓安装Docker。为此,我们将添加一个新的包源,添加来自Docker的GPG密钥以确保下载有效,然后安装软件包。

首先,更新您现有的软件包列表:

sudo apt update

接下来,安装一些先决条件包,让apt通过HTTPS使用软件包:

sudo apt install apt-transport-https ca-certificates curl software-properties-common

然后将官方Docker存储仓的GPG密钥添加到您的系统中:

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

将Docker存储仓添加到APT源:

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

再次更新您现有的软件包列表,以便识别添加内容:

sudo apt update

确保您要从Docker存储仓而不是默认的Ubuntu存储仓进行安装:

apt-cache policy docker-ce

你会看到类似的输出,Docker的版本号可能不同:

docker-ce:
  Installed: 5:23.0.1-1~ubuntu.22.04~jammy
  Candidate: 5:23.0.1-1~ubuntu.22.04~jammy
  Version table:
 *** 5:23.0.1-1~ubuntu.22.04~jammy 500
        500 https://download.docker.com/linux/ubuntu jammy/stable amd64 Packages
        100 /var/lib/dpkg/status
     5:23.0.0-1~ubuntu.22.04~jammy 500
        500 https://download.docker.com/linux/ubuntu jammy/stable amd64 Packages
     5:20.10.23~3-0~ubuntu-jammy 500
        500 https://download.docker.com/linux/ubuntu jammy/stable amd64 Packages

请注意,docker-ce未安装,但安装候选来自Ubuntu 22.04(jammy)的Docker存储仓。

最后,安装Docker:

sudo apt install docker-ce

现在安装Docker,启动守护进程,并启用启动时启动的进程。检查它是否正在运行:

sudo systemctl status docker

输出类似于以下内容,表明该服务处于启用状态并正在运行:

● docker.service - Docker Application Container Engine
     Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
     Active: active (running) since Mon 2023-02-20 15:53:30 CST; 3min 29s ago
TriggeredBy: ● docker.socket
       Docs: https://docs.docker.com
   Main PID: 1088 (dockerd)
      Tasks: 23
     Memory: 125.2M
        CPU: 3.375s
     CGroup: /system.slice/docker.service
             └─1088 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

现在安装Docker不仅可以提供Docker服务(守护进程),还可以提供docker命令行实用程序或Docker客户端。我们将在本教程后面探讨如何使用docker命令。

无Sudo执行Docker命令(选修)

默认情况下,docker命令只能由root用户或docker用户组运行,docker用户组是在Docker安装过程中自动创建。如果您尝试在不使用sudo前缀或不在docker用户组中的情况下运行docker命令,您将获得如下输出:

docker: Cannot connect to the Docker daemon. Is the docker daemon running on this host?.
See 'docker run --help'.

如果您想在运行docker命令时避免键入sudo,请将您的用户名添加到docker用户组:

sudo usermod -aG docker ${USER}

要应用新的组员级别,请退出服务器并重新登录,或键入以下内容:

su - ${USER}

系统将提示您输入用户密码以继续。

通过键入以下内容确认您的用户现在已添加到docker用户组:

groups
输出
edal sudo docker

如果您需要将用户添加到您未登录的docker用户组,请声明该用户名:

sudo usermod -aG docker 用户名

本文的其余部分以docker用户组中的用户身份运行docker命令为示例。如果您不想这样做,请在命令前加上sudo。

接下来让我们来实践docker命令。

Docker命令的运用

使用docker包括向其传递一系列选项和命令,然后是参数。语法采用以下形式:

docker [选项] [命令] [参数]

要查看所有可用的子命令,请键入:

docker

Docker版本23.0.1可用子命令的完整列表如下:

Commands:
  attach      Attach local standard input, output, and error streams to a running container
  commit      Create a new image from a container's changes
  cp          Copy files/folders between a container and the local filesystem
  create      Create a new container
  diff        Inspect changes to files or directories on a container's filesystem
  events      Get real time events from the server
  export      Export a container's filesystem as a tar archive
  history     Show the history of an image
  import      Import the contents from a tarball to create a filesystem image
  inspect     Return low-level information on Docker objects
  kill        Kill one or more running containers
  load        Load an image from a tar archive or STDIN
  logs        Fetch the logs of a container
  pause       Pause all processes within one or more containers
  port        List port mappings or a specific mapping for the container
  rename      Rename a container
  restart     Restart one or more containers
  rm          Remove one or more containers
  rmi         Remove one or more images
  save        Save one or more images to a tar archive (streamed to STDOUT by default)
  start       Start one or more stopped containers
  stats       Display a live stream of container(s) resource usage statistics
  stop        Stop one or more running containers
  tag         Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
  top         Display the running processes of a container
  unpause     Unpause all processes within one or more containers
  update      Update configuration of one or more containers
  wait        Block until one or more containers stop, then print their exit codes

要查看特定命令可用的选项,请键入:

docker docker-subcommand --help

要查看有关Docker的系统范围信息,请使用:

docker info

让我们探索其中的一些命令。我们将从处理镜像开始。

使用Docker镜像

Docker容器通过Docker镜像构建。默认情况下,Docker从Docker Hub中提取这些镜像,这是一个由Docker项目公司管理的Docker注册中心,任何人都可以在Docker Hub上托管他们的Docker镜像,因此您需要的大多数应用程序和Linux发行版都在那里有托管的镜像。

要检查您是否可以从Docker Hub访问和下载镜像,请键入:

docker run hello-world

输出将显示Docker正常工作:

Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
2db29710123e: Pull complete
Digest: sha256:6e8b6f026e0b9c419ea0fd02d3905dd0952ad1feea67543f525c73a0a790fefb
Status: Downloaded newer image for hello-world:latest

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

...

Docker初始无法在本地找到hello-world镜像,因此它从默认存储仓Docker Hub下载该镜像。下载镜像后,Docker从镜像创建一个容器并在容器内执行应用程序同时显示消息。

您可以使用带有search子命令的docker命令来搜索Docker Hub上可用的镜像。 例如,要搜索Ubuntu镜像,请键入:

docker search ubuntu

该脚本将抓取Docker Hub并返回名称与搜索字符串匹配的所有镜像列表。在这种情况下,输出将类似于以下信息:

NAME                             DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
ubuntu                           Ubuntu is a Debian-based Linux operating sys…   15619     [OK]
websphere-liberty                WebSphere Liberty multi-architecture images …   291       [OK]
open-liberty                     Open Liberty multi-architecture images based…   57        [OK]
neurodebian                      NeuroDebian provides neuroscience research s…   98        [OK]
ubuntu-debootstrap               DEPRECATED; use "ubuntu" instead                50        [OK]

...

在OFFICIAL栏中,OK表示由项目背后的公司构建和支持的镜像。 确定要使用的镜像后,您可以使用pull子命令将其下载到您的计算机上。

执行以下命令将官方ubuntu镜像下载到您的计算机:

docker pull ubuntu

您将看到所显示的信息如下:

Using default tag: latest
latest: Pulling from library/ubuntu
Digest: sha256:9a0bdde4188b896a372804be2384015e90e3f84906b750c1a53539b585fbbe7f
Status: Image is up to date for ubuntu:latest
docker.io/library/ubuntu:latest

下载镜像后,您可以通过下载的镜像使用run子命令运行容器。正如您在hello-world示例中看到的那样,如果在使用run子命令执行docker时尚未下载镜像,则Docker客户端将先下载镜像,然后使用它运行容器。

要查看已下载到您的计算机的图像,请键入:

docker images

您将看到所显示的信息如下:

hello-world                latest          feb5d9fea6a5   17 months ago   13.3kB
ubuntu                     20.04           e40cf56b4be3   2 weeks ago     72.8MB
ubuntu                     22.04           58db3edaf2be   3 weeks ago     77.8MB
ubuntu                     latest          58db3edaf2be   3 weeks ago     77.8MB

如您将在本文后面看到的那样,您可以修改用于运行容器的镜像并用于生成新镜像,然后可以将这些镜像上传/推送(推送是技术术语)到Docker Hub或其他Docker注册中心。

下面,让我们更详细地了解如何运行容器。

运行Docker容器

您在以上运行的hello-world容器是在发出测试消息后运行和退出的容器示例。容器可不仅仅有这样的功能,且容器可以进行交互使用。毕竟,它们类似于虚拟机,只是对资源运用更为友好。

例如,让我们使用最新的Ubuntu镜像运行一个容器。-i和-t组合使您可以通过交互式shell访问容器:

docker run -it ubuntu

您的命令提示应该更改以反映您现在在容器内工作的情况,且如下所示:

输出信息
root@c1c84b562c09:/#

请注意命令提示中的容器ID。在此示例中为c1c84b562c09。稍后您将需要该容器ID以在您想要删除它时识别该容器。

现在您可以在容器内运行任何命令。例如,让我们更新容器内的包数据库。您不需要在任何命令前加上sudo前缀,因为您是以root用户身份在容器内操作:

root@eb0d0364eb18:/# apt update

然后可以在其中安装任何应用程序,让我们安装Node.js看看:

root@6327df395f88:/# apt install nodejs

这会将Node.js安装在来自官方Ubuntu存储仓的容器中。 安装完成后,验证是否安装了Node.js:

root@eb0d0364eb18:/# node -v

您会在终端中看到版本号:

输出信息
v12.22.9

您在容器内所做的任何更改仅适用于该容器。

要退出容器,请在提示符处键入exit

接下来让我们管理系统上的容器。

Docker容器管理

使用Docker一段时间后,您的计算机上将有许多启用(运行)和非启用容器。要查看启用容器,请使用:

docker ps

您将看到所显示的信息如下:

CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

本文中,您启动了两个容器;一个来自hello-world镜像,另一个来自ubuntu镜像。两个容器都不再运行,但它们仍然存在于您的系统中。

要查看所有容器——启用或非启用,使用-a运行docker ps

docker ps -a

您将看到所显示的信息如下:

CONTAINER ID   IMAGE         COMMAND       CREATED            STATUS                      PORTS   NAMES
6327df395f88   ubuntu        "/bin/bash"   36 minutes ago     Exited (129) 27 minutes ago         flamboyant_darwin
eb0d0364eb18   ubuntu        "/bin/bash"   56 minutes ago     Exited (129) 50 minutes ago         eloquent_poincare
c1c84b562c09   ubuntu        "/bin/bash"   About an hour ago  Exited (129) 57 minutes ago         competent_stonebraker
d5741949647c   hello-world   "/hello"      2 hours ago        Exited (0) 2 hours ago              optimistic_nobel

要查看您创建的最新容器,就使用 -l

docker ps -l
CONTAINER ID   IMAGE     COMMAND       CREATED          STATUS                        PORTS     NAMES
6327df395f88   ubuntu    "/bin/bash"   54 minutes ago   Exited (129) 45 minutes ago             flamboyant_darwin

要启动已停止的容器,请使用 docker start,后跟容器ID或容器名称。让我们启动ID为6327df395f88的基于Ubuntu的容器:

docker start 6327df395f88

容器将启动,您可以使用 docker ps 查看其状态:

CONTAINER ID   IMAGE     COMMAND       CREATED          STATUS          PORTS     NAMES
6327df395f88   ubuntu    "/bin/bash"   59 minutes ago   Up 22 seconds             flamboyant_darwin

要停止正在运行的容器,请使用 docker stop,后跟容器ID或名称。这一次,我们将使用Docker分配给容器的名称,即flamboyant_darwin:

docker stop flamboyant_darwin

一旦你决定不再需要一个容器,使用 docker rm 命令删除它,再次使用容器ID或名称。使用 docker ps -a 命令查找与hello-world镜像关联的容器ID或名称并将其删除。

docker rm flamboyant_darwin

您可以启动一个新容器并使用 --name 为其命名。您还可以使用 --rm 创建一个在停止时自行删除的容器。有关这些选项和其他选项的更多信息,请参阅 docker run help 命令。

容器可以变成镜像,你可以用它来构建新的容器。让我们看看如何实现。

将容器更改提交至Docker镜像

启动Docker镜像时,您可以像使用虚拟机一样创建、修改和删除文件。您所做的更改将仅可用于该容器。您可以启动和停止它,但一旦您使用 docker rm 命令销毁,所做的更改将永远丢失。

在此向您展示如何将容器的状态保存为新的Docker镜像。

在Ubuntu容器中安装Node.js后,您现在有一个运行镜像的容器,但该容器与您用来创建它的镜像不同。但是您以后可能想基于这个Node.js容器制作新镜像。

然后使用以下命令将更改提交到新的Docker镜像实例。

docker commit -m "您的提交注解" -a "作者名称" container_id repository/new_image_name

-m 用于提交信息注解,可帮助您和其他人了解您所做的更改,而 -a 用于指定作者。container_id是您在本文前面开始交互式Docker会话时记下的那个。 除非您在Docker Hub上创建了额外的存储仓,否则存储仓repository通常是您的Docker Hub用户名。

例如,对于容器ID为c1c84b562c09的用户edal,命令为:

docker commit -m "添加Node.js" -a "edal" c1c84b562c09 edal/ubuntu-nodejs

当您提交镜像时,新镜像会保存在您本地的计算机上。 在本文的后面,您将学习如何将镜像推送到Docker Hub等Docker注册中心,以便其他人可以访问或使用。

再次列出Docker镜像将显示新镜像,以及它派生自的旧镜像:

docker images

您将看到所显示的信息如下:

REPOSITORY                 TAG             IMAGE ID       CREATED          SIZE
edal/ubuntu-nodejs        latest          e68a2e992e29   12 seconds ago   77.8MB

...

在此示例中,ubuntu-nodejs是新镜像,它派生自Docker Hub中现有的ubuntu镜像。大小差异反映了所做的更改。在这个例子中,变化是安装了NodeJS。因此,下次您需要使用预安装了NodeJS的Ubuntu运行容器时,您只需使用新镜像即可。

您还可以通过Dockerfile构建镜像,这样您就可以在新镜像中自动安装软件。但这超出了本文要分享的内容范围。

现在让我们与其他人共享新镜像,以便其他人可以从中创建容器。

将镜像推送到Docker存储仓

从现有镜像创建新镜像后的下一个合乎逻辑的步骤是在Docker Hub或您有权访问的其他Docker注册中心上与您的几个朋友、整个世界共享。要将镜像推送到Docker Hub或任何其他Docker注册中心,您必须在那里拥有一个帐户。

要推送您的图像,请先登录Docker Hub。

docker login -u 用户名

系统将提示您使用Docker Hub密码进行身份验证,如果您指定了正确的密码,则身份验证就会成功。

如果您的Docker注册中心用户名与您用于创建映像的本地用户名不同,您将必须使用您的注册中心用户名标记您的镜像。对于最后一步中给出的示例,您将键入:

docker tag edal/ubuntu-nodejs docker用户名/ubuntu-nodejs

然后你可以使用以下方式推送你自己的镜像:

docker push docker用户名/镜像名称

要将ubuntu-nodejs镜像推送到edal存储仓,命令为:

docker push edal/ubuntu-nodejs

该过程在上传镜像时可能需要一些时间才能完成,但完成后,输出将如下所示:

The push refers to a repository [docker.io/edal/ubuntu-nodejs]
a3fbbfb44187: Pushed
df70bf19a086: Pushed
43b5c90a4eba: Pushed
7f18c442962b: Pushed
gce512daaf98: Pushed
6aae4313b42d: Pushed

将镜像推送到注册中心后,它应该列在您帐户的仪表板上,如下图所示。

Docker全方位攻略与自动化运维

如果推送尝试导致此类错误,那么您可能没有登录:

The push refers to a repository [docker.io/edal/ubuntu-nodejs]
a3fbbfb44187: Preparing
df70bf19a086: Preparing
43b5c90a4eba: Preparing
7f18c442962b: Preparing
gce512daaf98: Preparing
6aae4313b42d: Waiting
unauthorized: authentication required

使用 docker login 登录并重复推送尝试。 然后验证是否存在于您的Docker Hub存储仓页面上。

您现在可以使用 docker pull edal/ubuntu-nodejs 将镜像拉取到新机器并使用它来运行新容器。

安装Docker Compose

为确保您获得最新的Docker Compose稳定版本,您将从其官方Github存储仓下载该软件。

首先,确认其发布页面中可用的最新版本。在撰写本文时,最新的稳定版本是2.16.0

使用以下命令下载:

mkdir -p ~/.docker/cli-plugins/
curl -SL https://github.com/docker/compose/releases/download/v2.16.0/docker-compose-linux-x86_64 -o ~/.docker/cli-plugins/docker-compose

接下来,设置正确的权限,以便 docker compose 命令可执行:

chmod +x ~/.docker/cli-plugins/docker-compose

欲验证安装是否成功,您可以运行:

docker compose version

您将看到所显示的信息如下:

Docker Compose version v2.16.0

Docker Compose现已成功安装在您的系统上。接下来,我们将了解如何设置 docker-compose.yml 文件并使用此工具启动和运行容器化环境。

设置docker-compose.yml

为演示如何设置docker-compose.yml文件并使用Docker Compose,您将使用来自Docker Hub(公共Docker注册中心)的官方Nginx镜像创建一个Web服务器环境。此容器化环境将提供单个静态HTML文件。

首先在您的主文件夹中新建一个目录,然后转到其中:

mkdir ~/compose-demo
cd ~/compose-demo

在此目录中,设置一个应用程序文件夹作为Nginx环境的文档根目录:

mkdir app

使用您喜欢的文本编辑器,在 app 文件夹中新建一个index.html文件:

vim app/index.html

然后,在文件中输入以下代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Docker Compose 示例</title>
</head>
<body>

    <h1>这是一个Docker Compose示例页面</h1>
    <p>此内容由Nginx容器服务显示</p>
    
</body>
</html>

接下来,创建 docker-compose.yml 文件:

vim docker-compose.yml

在您的docker-compose.yml文件中插入以下内容:

version: '3.8'
services:
  web:
    image: nginx:alpine
    ports:
      - "8000:80"
    volumes:
      - ./app:/usr/share/nginx/html

docker-compose.yml文件通常以版本定义开头,告诉Docker Compose您正在使用哪个配置版本。

然后您有服务模块,您可以在其中设置属于此环境的服务。在本例中,您有一个名为web的服务。此服务使用nginx:alpine镜像并使用ports指令设置端口重定向。主机(运行 Docker Compose的系统)端口8000上的所有请求都将重定向到端口80上的Web容器,Nginx将在其中运行。

volumes指令将在主机和容器之间创建一个共享卷。这将与容器共享本地应用程序文件夹,卷将位于容器内的/usr/share/nginx/html,然后将覆盖Nginx的默认文档根目录。

您已经设置了一个演示页面和一个docker-compose.yml文件来创建一个容器化的Web服务器环境为其提供服务。在下一步中,我们将使用Docker Compose启动此环境。

运行Docker Compose

有了docker-compose.yml 文件,您现在可以执行Docker Compose来启动您的环境。以下命令将下载必要的Docker镜像,为Web服务创建容器,并在后台模式下运行容器化环境:

docker compose up -d

Docker Compose将先在您的本地系统上查找定义的镜像,如果找不到该镜像,将自动从Docker Hub下载。

您的环境现已启动并在后台运行。要验证容器是否处于启用状态,您可以运行:

docker compose ps

此命令将向您显示有关正在运行的容器及其状态的信息,以及当前存在的任何端口重定向:

NAME                 IMAGE          COMMAND                  SERVICE   CREATED         STATUS         PORTS
compose-demo-web-1   nginx:alpine   "/docker-entrypoint.…"   web       31 seconds ago  Up 27 seconds  0.0.0.0:8000->80/tcp, :::8000->80/tcp

您现在可以通过将浏览器指向localhost:8000(本地机器上运行此演示)或您的域名或服务器IP:8000(远程服务器上运行此演示)来访问演示应用程序。

你会看到类似如下页面:

Docker全方位攻略与自动化运维

Docker Compose命令

您已了解如何设置docker-compose.yml文件并使用docker compose启动您的环境。下面,我们来了解如何使用Docker Compose命令来管理容器化环境并与之交互。

要检查Nginx容器生成的日志,可以使用 logs 命令:

docker compose logs

您将看到所显示的信息如下:

edal@buddy:~/compose-demo$ docker compose logs
compose-demo-web-1  | /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
compose-demo-web-1  | /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
compose-demo-web-1  | /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
compose-demo-web-1  | 10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
compose-demo-web-1  | 10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
compose-demo-web-1  | /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
compose-demo-web-1  | /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
compose-demo-web-1  | /docker-entrypoint.sh: Configuration complete; ready for start up
compose-demo-web-1  | 2023/02/21 08:20:53 [notice] 1#1: using the "epoll" event method
compose-demo-web-1  | 2023/02/21 08:20:53 [notice] 1#1: nginx/1.23.3

...

如果您想在不更改容器当前状态的情况下暂停环境执行,您可以使用:

docker compose pause

发出暂停后恢复运行:

docker compose unpause

stop命令将终止容器执行,但它不会破坏与容器关联的任何数据:

docker compose stop

如果要删除与此容器化环境关联的容器、网络和卷,请使用down命令:

docker compose down

注:这不会删除Docker Compose用来启动您的环境的基础镜像(本示例中为nginx:alpine)。每当您使用 docker compose up 再次启动您的环境时,由于镜像已经在您的系统上,因此该过程会很快。

如果您还想从系统中删除基本映像,可以使用:

docker image rm nginx:alpine

您将看到所显示的信息如下:

Untagged: nginx:alpine
Untagged: nginx@sha256:6f94b7f4208b5d5391246c83a96246ca204f15eaf7e636cefda4e6348c8f6101
Deleted: sha256:2bc7edbc3cf2fce630a95d0586c48cd248e5df37df5b1244728a5c8c91becfe0
Deleted: sha256:9ca6be4cd63171f17f0a5e2ea28d5361a299672f41bd65223e7eac7d3d57e76d
Deleted: sha256:f7aa4d1226879fb1018ed05617572994840f4c75e5d04df2fffe04980cef11b9
Deleted: sha256:f83cdd3286b839bef51f1ae0f1f6164b16e1059a0e131035bfa0bb8bb0021357
Deleted: sha256:61b0680052fcdb48f47c8d68687c0b5bbb279b6e3740701885b39ea22ef7b008
Deleted: sha256:9045770a1273553bb8bd7ccd2d490ecb56ce762ac993ad74698d14186e39bda6
Deleted: sha256:60d9493158e562e8510cd4cabbd7460c03ad39fe2250bbd43bdcd1e75f64ba6f
Deleted: sha256:7cd52847ad775a5ddc4b58326cf884beee34544296402c6292ed76474c686d39

您已经了解了如何安装Docker Compose并基于Nginx Web服务器镜像设置容器化环境。同时,您还了解了如何使用Compose命令管理环境。

下面,我们来为设置私有的Docker注册中心做好准备:

安装Nginx

Nginx是世界上最流行的Web服务器之一,负责托管互联网上一些最大和最高流量的网站。它是一个轻量级的选择,可以用作Web服务器或反向代理。

因为Nginx在Ubuntu的默认存储仓中可用,所以可以使用apt打包系统从存储库安装。

运行以下命令快速安装Nginx:

sudo apt update
sudo apt install nginx

当提示确认安装时按Y。如果系统提示您重新启动任何服务,请按回车键接受默认值并继续。apt将安装Nginx和任何必需的依赖项到您的服务器。

调整防火墙

在测试Nginx之前,需要配置防火墙软件以允许访问该服务。Nginx在安装时将自己注册为ufw的服务,从而可以直接允许Nginx访问。

通过键入以下内容列出ufw知道如何使用的应用程序配置:

sudo ufw app list

您将看到所显示的信息如下:

Available applications:
  Nginx Full
  Nginx HTTP
  Nginx HTTPS
  OpenSSH

如输出所示,Nginx 可以使用三个配置文件:

  • Nginx Full:此配置文件同时打开端口80(正常、未加密的Web访问)和端口 443(TLS/SSL加密访问)
  • Nginx HTTP:此配置文件仅打开端口80(正常、未加密的网络访问)
  • Nginx HTTPS:此配置文件仅打开端口443(TLS/SSL加密访问)

建议您启用限制最严格的配置文件,该配置文件仍将允许您配置的流量。现在,我们只需要允许端口80上的访问。

您可以通过键入以下内容启用此功能:

sudo ufw allow 'Nginx HTTP'

您可以通过键入以下内容来验证更改:

sudo ufw status

您将看到所显示的信息如下:

Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere                  
Nginx HTTP                 ALLOW       Anywhere                  
OpenSSH (v6)               ALLOW       Anywhere (v6)             
Nginx HTTP (v6)            ALLOW       Anywhere (v6)

查看您的Web服务器

在安装过程结束时,Ubuntu 22.04启动Nginx。Web服务器应该已经启动并正在运行。

我们可以通过键入以下命令检查systemd初始化系统以确保服务正在运行:

systemctl status nginx
● nginx.service - A high performance web server and a reverse proxy server
     Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
     Active: active (running) since Mon 2023-02-20 22:53:14 CST; 1min 30s ago
       Docs: man:nginx(8)
    Process: 19990 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
    Process: 19991 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
   Main PID: 20091 (nginx)
      Tasks: 13 (limit: 18902)
     Memory: 11.3M
        CPU: 210ms
     CGroup: /system.slice/nginx.service
             ├─20091 "nginx: master process /usr/sbin/nginx -g daemon on; master_process on;"
             ├─20094 "nginx: worker process

由此确认,该服务已成功启动。然而,最好的测试方法是实际从Nginx请求一个页面。

您可以访问默认的Nginx页面,通过导航到您服务器的IP地址来确认软件是否正常运行。如果您不知道服务器的IP地址,可以使用icanhazip.com工具找到,该工具将为您提供从互联网上其他位置收到的公共IP地址:

curl -4 icanhazip.com

获得服务器的IP地址后,将其输入浏览器的地址栏:

http://您的IP地址

您应该会收到默认的Nginx访问页面:

Docker全方位攻略与自动化运维

Nginx进程管理

现在您已经启动并运行了Web服务器,让我们回顾一些基本的管理命令。

欲停止您的Web服务器,请键入:

sudo systemctl stop nginx

启动Web服务器:

sudo systemctl start nginx

重启Web服务器:

sudo systemctl restart nginx

如果您只是进行配置更改,Nginx通常可以在不断开连接的情况下重新加载。为此,请键入:

sudo systemctl reload nginx

默认情况下,Nginx配置为在服务器启动时自动启动。如果您不想如此,可以通过键入以下内容来停用此方式:

sudo systemctl disable nginx

欲重新启用该服务以在引导时启动,您可以键入:

sudo systemctl enable nginx

您现在已经学习了基本的管理命令,并且应该准备好配置站点以托管多个域名。

设置服务器模块(推荐)

使用Nginx网络服务器时,服务器模块(类似于Apache中的虚拟主机)可用于封装配置具体信息并从一台服务器托管多个域名。我们将设置一个名为your_domain的域名,实际情况下您需要将其替换为您自己的域名。

Ubuntu 22.04上的Nginx默认启用一个服务器模块,该服务器模块配置为从/var/www/html目录中提供文档。虽然这适用于单个站点,但如果您托管多个站点,可能会变得笨拙。我们不修改/var/www/html,而是在/var/www中为我们的your_domain站点创建一个目录结构,将/var/www/html保留为默认目录,以便在客户端请求不匹配时提供服务其他网站。

如下所示为your_domain创建目录,使用-p标志创建任何必要的上级目录:

sudo mkdir -p /var/www/your_domain/html

接下来,使用 $USER 环境变量分配目录的所有权:

sudo chown -R $USER:$USER /var/www/your_domain/html

如果您没有修改设置默认文件权限的umask值,您的Web根目录的权限应该是正确的。为确保您的权限正确并允许所有者读取、写入和执行文件,同时授予组和其他仅读取和执行权限,您可以输入以下命令:

sudo chmod -R 755 /var/www/your_domain

接下来,使用vim或您喜欢的编辑器创建一个示例index.html页面:

sudo vim /var/www/your_domain/html/index.html

在以上文件里添加以下HTML代码示例:

<html>
    <head>
        <title>your_domain 欢迎您!</title>
    </head>
    <body>
        <h1>搞定! your_domain服务器模块运行正常!</h1>
    </body>
</html>

为了让Nginx内容提供服务,有必要使用正确的指令创建一个服务器模块。我们不直接修改默认配置文件,而是在/etc/nginx/sites-available/your_domain新建一个:

sudo vim /etc/nginx/sites-available/your_domain

粘贴以下配置模块,它与默认配置类似,但针对我们的新目录和域名进行了更新:

server {
        listen 80;
        listen [::]:80;

        root /var/www/your_domain/html;
        index index.html index.htm index.nginx-debian.html;

        server_name your_domain www.your_domain;

        location / {
                try_files $uri $uri/ =404;
        }
}

请注意,我们已将root配置更新为我们的新目录,并将 server_name 更新为我们的域名。

接下来,让我们通过创建一个到sites-enabled目录的链接来启用该文件,Nginx在启动期间从中读取:

sudo ln -s /etc/nginx/sites-available/your_domain /etc/nginx/sites-enabled/

Nginx使用一种称为symbolic链接或symlinks符号链接的常见做法来跟踪启用的服务器模块。创建一个符号链接就像在磁盘上创建一个快捷链接的方式,这样您可以稍后从启用站点的目录中删除该快捷方式,同时如果您想要启用,则将服务器模块保留在sites-available中。

为避免因添加额外的服务器名称而可能出现的哈希桶内存问题,有必要调整 /etc/nginx/nginx.conf 文件中的单个值。 打开文件:

sudo vim /etc/nginx/nginx.conf

找到 server_names_hash_bucket_size 指令并删除 # 符号以取消注释该行。

...
http {
    ...
    server_names_hash_bucket_size 64;
    ...
}
...

接下来,测试以确保您的Nginx文件中没有任何语法错误:

sudo nginx -t

如果没有任何问题,请重新启动Nginx以启用您的更改:

sudo systemctl restart nginx

Nginx现在应该为您的域名提供服务。您可以通过浏览器访问http://your_domain 来进行测试,您会在页面上看到如下内容:

搞定! your_domain服务器模块运行正常!

熟悉Nginx重要文件与目录

现在您知道如何管理Nginx服务本身,您应该花几分钟时间熟悉一些重要的目录和文件。

内容部分

  • /var/www/html:为Web内容,默认情况下仅包含您之前看到的默认Nginx页面,由/var/www/html目录提供。这可以通过更改Nginx配置文件来更改。

服务器配置

  • /etc/nginx:Nginx配置目录,所有Nginx配置文件都驻留在此处。
  • /etc/nginx/nginx.conf:主要Nginx配置文件,可以修改以变更Nginx全局配置。
  • /etc/nginx/sites-available/:可以存储每个站点服务器模块的目录。Nginx不会使用在此目录中找到的配置文件,除非将其链接到sites-enabled目录。通常,所有服务器模块配置都在此目录中完成,然后通过链接到其他目录来启用。
  • /etc/nginx/sites-enabled/:存储启用每站点服务器模块的目录。通常是通过链接到sites-available目录中的配置文件来进行创建。
  • /etc/nginx/snippets:该目录含有配置片段,可包含在Nginx配置的其他地方。潜藏可重复的配置片段是重构为片段的备用者。

服务器日志

  • /var/log/nginx/access.log:除非Nginx配置为其他方式,否则对Web服务器的每个请求都会记录在此日志文件中。
  • /var/log/nginx/error.log:任何Nginx错误都将记录在此日志中。

安装Let's Encrypt SSL证书

安装Certbot

Certbot建议使用他们的snap包进行安装。Snap包适用于几乎所有Linux发行版,但它们要求您先安装snapd才能管理snap包。Ubuntu 22.04支持开箱即用的 snap,因此您可以先确保您的snapd核心为最新更新:

sudo snap install core; sudo snap refresh core

如果您安装了旧版本certbot在服务器上,则应在继续之前将其删除:

sudo apt remove certbot

之后,您就可以安装certbot包啦:

sudo snap install --classic certbot

最后,您可以将certbot命令从snap安装目录链接到您的路径,这样您就可以通过键入certbot来运行。并非所有包都需要这样做,但默认情况下snap的侵入性较低,因此它们不会意外地与任何其他系统包发生冲突:

sudo ln -s /snap/bin/certbot /usr/bin/certbot

现在我们已经安装了Certbot,下面运行它来获取SSL证书。

获取SSL证书

Certbot提供了多种通过插件获取SSL证书的方式,插件将负责重新配置Nginx并在必要时重新加载配置。要使用此插件,请键入以下内容:

sudo certbot --nginx -d your_domain -d www.your_domain

以上命令使用 --nginx 插件运行certbot,使用 -d 指定我们希望证书有效的域名。

运行命令时,系统会提示您输入电子邮件地址并同意服务条款。执行此操作后,您应该会看到如下相关证书存储位置的一条消息:

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/your_domain/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/your_domain/privkey.pem
This certificate expires on 2023-05-21.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.

Deploying certificate
Successfully deployed certificate for your_domain to /etc/nginx/sites-enabled/your_domain
Successfully deployed certificate for www.your_domain to /etc/nginx/sites-enabled/your_domain
Congratulations! You have successfully enabled HTTPS on https://your_domain and https://www.your_domain

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
If you like Certbot, please consider supporting our work by:
 * Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
 * Donating to EFF:                    https://eff.org/donate-le
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

您的证书已下载、安装和加载,您的Nginx配置现在将自动将所有Web请求重定向到https://。试着重新加载您的网站并注意浏览器的安全指示器。它应该表明该站点已得到妥善保护,通常带有锁图标。

Certbot自动更新

Let's Encrypt的证书有效期只有九十天。我们安装的certbot包通过添加一个每天运行两次的systemd计时器来为我们解决这个问题,并自动更新任何在三十天内到期的证书。

您可以使用systemctl查询定时器的状态:

sudo systemctl status snap.certbot.renew.service

您将看到所显示的信息如下:

○ snap.certbot.renew.service - Service for snap application certbot.renew
     Loaded: loaded (/etc/systemd/system/snap.certbot.renew.service; static)
     Active: inactive (dead)
TriggeredBy: ● snap.certbot.renew.timer

欲测试更新续订过程,您可以使用certbot进行试运行:

sudo certbot renew --dry-run

如果您没有看到任何错误,则一切就绪。必要时,Certbot将更新您的证书并重新加载Nginx以获取更改。如果自动续订过程失败,Let's Encrypt将向您指定的电子邮件发送一条消息,在您的证书即将过期时通知您。

设置私有Docker注册中心

安装与配置Docker注册中心

在启动和测试容器时,命令行上运行Docker很有用,但对于涉及并行运行多个容器的更大部署,可能会变得笨拙。

使用Docker Compose,您可以编写一个 .yml 文件来设置每个容器的配置和容器相互通信所需信息。您可以使用 docker compose 工具向组成应用程序的所有组件发出命令,并将它们作为一个组进行控制。

Docker Registry(Docker注册中心) 本身是一个包含多个组件的应用程序,因此您可使用Docker Compose来进行管理。要启动注册中心实例,您需设置一个 docker-compose.yml文件来定义以及注册中心将在磁盘上存储其数据的位置。

在此,我们将配置存储在主机服务器上名为 docker-registry 的目录中。通过运行以下命令创建:

mkdir ~/docker-registry

转向改目录:

cd ~/docker-registry

在目录下再创建一个名为data的子目录:

mkdir data

通过运行以下命令创建并打开名为 docker-compose.yml 的文件:

vim docker-compose.yml

添加以代码将其定义Docker注册中心的基本实例:

version: '3.8'

services:
  registry:
    image: registry:latest
    ports:
    - "5000:5000"
    environment:
      REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
    volumes:
      - ./data:/data

以上文件,您命名第一个服务 registry ,使用 registry 镜像并将其设置到最新版本。然后,在端口下,将主机上的端口 5000 映射到容器的端口 5000 ,这将允许您向服务器上的端口 5000 发送请求并将请求转发到注册中心。

environment 部分,设置 REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY 变量至 /data ,指定应在哪个卷中存储其数据。然后,在 volumes 部分,将主机文件系统上的 /data 目录映射到容器中的 /data 通行使用。数据实际上将存储在主机的文件系统中。

保存并退出文件编辑页面

您现在可以通过运行以下命令开始配置:

docker compose up

注册中心容器及其依赖项将被下载并启动。

[+] Running 6/6
 ⠿ registry Pulled                                                                                                                                                7.7s
   ⠿ ef5531b6e74e Pull complete                                                                                                                                   2.7s
   ⠿ a52704366974 Pull complete                                                                                                                                   2.8s
   ⠿ dda5a8ba6f46 Pull complete                                                                                                                                   2.9s
   ⠿ eb9a2e8a8f76 Pull complete                                                                                                                                   3.3s
   ⠿ 25bb6825962e Pull complete                                                                                                                                   3.9s
[+] Running 2/1
 ⠿ Network docker-registry_default       Created                                                                                                                  0.1s
 ⠿ Container docker-registry-registry-1  Created                                                                                                                  0.0s
Attaching to docker-registry-registry-1
docker-registry-registry-1  | time="2023-02-21T19:08:16.67735615Z" level=warning msg="No HTTP secret provided - generated random secret. This may cause problems with uploads if multiple registries are behind a load-balancer. To provide a shared secret, fill in http.secret in the configuration file or set the REGISTRY_HTTP_SECRET environment variable." go.version=go1.16.15 instance.id=9bd45996-08d9-4812-898f-43378f81ef5f service=registry version="v2.8.1+unknown"
docker-registry-registry-1  | time="2023-02-21T19:08:16.677440318Z" level=info msg="redis not configured" go.version=go1.16.15 instance.id=9bd45996-08d9-4812-898f-43378f81ef5f service=registry version="v2.8.1+unknown"
docker-registry-registry-1  | time="2023-02-21T19:08:16.677708003Z" level=info msg="Starting upload purge in 0s" go.version=go1.16.15 instance.id=9bd45996-08d9-4812-898f-43378f81ef5f service=registry version="v2.8.1+unknown"
docker-registry-registry-1  | time="2023-02-21T19:08:16.677753999Z" level=info msg="PurgeUploads starting: olderThan=2023-02-14 19:08:16.67772287 +0000 UTC m=-604799.990567511, actuallyDelete=true"

...

设置Nginx端口转向

您已经设置了/etc/nginx/sites-available/your_domain文件,其中包含您的服务器配置。通过运行打开它进行编辑:

sudo vim /etc/nginx/sites-available/your_domain

找到现有的location模块:

...
        location / {
  ...
        }
...

您需要将访问转发到端口5000,您的注册中心将在此处侦听访问。您还希望将标头附加转发到注册中心的请求,它提供来自服务器的关于请求本身的附加信息。用以下代码替换location模块的现有内容:

...
location / {
    # Do not allow connections from docker 1.5 and earlier
    # docker pre-1.6.0 did not properly set the user agent on ping, catch "Go *" user agents
    if ($http_user_agent ~ "^(docker\/1\.(3|4|5(?!\.[0-9]-dev))|Go ).*$" ) {
      return 404;
    }

    proxy_pass                          http://localhost:5000;
    proxy_set_header  Host              $http_host;   # required for docker client's sake
    proxy_set_header  X-Real-IP         $remote_addr; # pass on real client's IP
    proxy_set_header  X-Forwarded-For   $proxy_add_x_forwarded_for;
    proxy_set_header  X-Forwarded-Proto $scheme;
    proxy_read_timeout                  900;
}
...

if模块检查请求的用户代理并验证Docker客户端的版本是否高于1.5,并且它不是尝试访问的Go应用程序。有关这方面的更多解释,您可以在Docker注册中心Nginx指南中找到nginx标头配置。

完成后保存并退出文件编辑页面。通过重新启动Nginx来应用更改:

sudo systemctl restart nginx

如果您收到出错消息,请仔细检查您添加的配置。

欲确认Nginx正确地将访问转发到端口 5000 上的注册表容器,请运行:

docker compose up

然后,在浏览器中,访问您的域名并使用v2端点,如下所示:

https://your_domain/v2

浏览器将加载一个空的JSON对象:

{}

设置身份验证

Nginx可以让您为其管理的站点设置HTTP身份验证,您可以使用它来限制对Docker注册中心的访问。为此,您将使用 htpasswd 创建一个身份验证文件,并向其中添加将被认可的用户名和密码组合。该过程将启用对您的注册中心的身份验证。

您可以通过安装 apache2-utils 软件包来获取 htpasswd 实用程序。运行以下命令:

sudo apt install apache2-utils -y

将带有凭据的身份验证文件存储在 ~/docker-registry/auth 下。运行以下命令:

mkdir ~/docker-registry/auth

转向该目录:

cd ~/docker-registry/auth

创建第一个用户,将用户名替换为您要使用的用户名。-B 标志命令使用Docker要求的bcrypt算法:

htpasswd -Bc registry.password 用户名

出现提示时输入密码。凭据的组合将附加到registry.password

要添加更多用户,请在不带 -c 的情况下重新运行之前的命令:

htpasswd -B registry.password 用户名

-c 为创建一个新文件,如果使用它会更新现有文件。

现在已创建凭据列表,我们需要编辑 docker-compose.yml 以命令Docker使用您创建的文件对用户进行身份验证。打开它进行编辑:

vim ~/docker-registry/docker-compose.yml

添加高亮代码部分:

version: '3.8'

services:
  registry:
    image: registry:latest
    ports:
    - "5000:5000"
    environment:
      REGISTRY_AUTH: htpasswd
      REGISTRY_AUTH_HTPASSWD_REALM: Registry
      REGISTRY_AUTH_HTPASSWD_PATH: /auth/registry.password
      REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
    volumes:
      - ./auth:/auth
      - ./data:/data

现在,您已添加了指定使用HTTP身份验证并提供 htpasswd 创建文件路径的环境变量。对于 REGISTRY_AUTH,将 htpasswd 指定为其值,并将 REGISTRY_AUTH_HTPASSWD_PATH 设置为身份验证文件的路径。REGISTRY_AUTH_HTPASSWD_REALM 表示 htpasswd 领域的名称。

您还挂载了 ./auth 目录以使该文件在注册中心容器内可用。保存并退出编辑文件页面。

现在可以验证您的身份验证是否正常工作。先转到到主目录:

cd ~/docker-registry

然后运行:

docker compose up

在您的浏览器中,刷新域名页面。系统会要求您提供用户名和密码。

提供有效的凭据组合后,您将访问带有空JSON对象的页面:

{}

您已成功通过身份验证并获得了对注册中心的访问权限。在终端中按CTRL+C退出运行。

您的注册中心现已有安全保障,只有在身份验证后才能访问。接下来,我们将配置它作为后台进程运行,同时通过自动启动来使用重新启动。

启动Docker注册中心即服务

您可以通过指示Docker Compose始终保持运行来确保注册中心容器在每次系统启动或崩溃后保持重启运行。

打开 docker-compose.yml 进行编辑:

vim docker-compose.yml

将以下高亮代码添加到registry模块中:

...
  registry:
    restart: always
...

您现在可以通过 -d 标志将注册中心作为后台进程启动:

docker compose up -d

当你的注册中心在后台运行时,你可以随意关闭这个SSH命令行界面,终端和注册中心不会受到影响。

由于Docker镜像的占用空间可能非常大,接下来我们将设置Nginx能够接受上传的最大文件尺寸限制。

Nginx文件上传大小设置

在将镜像推送到注册中心之前,您需要确保您的注册中心能够处理大文件上传。Nginx默认上传文件大小限制为1m,这对于Docker镜像来说远远不够。 接下来,我们将对其设置进行修改,编辑位于 /etc/nginx/nginx.conf 的Nginx配置文件。

打开文件进行编辑:

sudo vim /etc/nginx/nginx.conf

在http部分添加以下高亮代码内容:

...
http {
        client_max_body_size 8192m;
        ...
}
...

client_max_body_size 参数现设置为8192m,使最大上传大小为8GB。

保存并退出编辑文件页面。

重新启动Nginx以应用配置更改:

sudo systemctl restart nginx

发布至私有Docker注册中心

现在您设置好的Docker注册中心服务器正在运行并接受大文件8GB的上传,我们来试着将镜像推送到这个私有的Docker注册中心。由于您没有现成可用的景象,我们将使用来自 Docker Hub的ubuntu镜像进行测试。

在客户端服务器的新终端会话中,运行以下命令来下载ubuntu镜像,运行并访问其shell:

docker run -t -i ubuntu /bin/bash

进入后,通过运行以下命令创建一个名为 SUCCESS 的文件:

root@44ea1c653b1d:/# touch /SUCCESS

通过创建此文件,您已经自定义了您的容器。稍后将使用它来检查您是否使用完全相同的容器。

运行以下命令退出容器shell:

root@44ea1c653b1d:/# exit

现在从您刚刚自定义的容器新建一个镜像:

docker commit $(docker ps -lq) test-image

新镜像现在在本地已可用,您可以将其推送到您的容器注册中心。首先,您必须登录:

docker login https://your_domain

弹出登陆框时,输入相关在之前所创建的登陆信息即可。

一旦登陆之后,就可以重命名所创建的镜像:

docker tag test-image your_domain/test-image

最后,将新标记的镜像推送到您的注册中心:

docker push your_domain/test-image

拉取镜像自私有Docker注册中心

登陆私有Docker注册中心:

docker login https://your_domain

拉取test-image镜像:

docker pull your_domain/test-image

Docker将下载镜像。使用以下命令运行容器:

docker run -it your_domain/test-image /bin/bash

搞定!私有Docker注册中心已就绪!

DevOps与Docker完美结合

通过上面一系列的操作,我们已将相关Docker的环境全部就绪。之后就是我们即将面对的目标,开发一些属于我们自己的项目,并发布甚至将我们开发的产品进行商用,产品化我们的项目,最终达至盈利的目的。但在开发与运维的过程中我们将遇到各种各样的问题:测试、调试、修复Bugs、维护服务器、产品版本发布、SEO优化、代码质量提升、团队协作开发,甚至团队管理等等。因此,DevOps的概念给我们带来了很好的解决方案!什么是DevOps? 这问题我们就不在此详细讨论,您可以通过互联网搜索得到所要的答案。而在此部分,我们将使用Buddy做为DevOps开发运维示例。

什么是Buddy?

Buddy是一个DevOps自动化平台:一个让开发人员能够以简单可靠的方式构建、测试和发布软件的平台(支持云服务、本地部署与自托管部署)。它基于持续集成的原则,对代码的每次更改都会自动测错并为部署做好准备。部署也是自动化,这消除了人为错误风险并显著缩短操作时间。因此,您可以更快地收集客户的反馈并进行更改,而不会有白白浪费数月工作的风险。Buddy的使用有免费与收费两种帐户类型,在此,我们可以免费注册并使用它作为自动化运维Docker项目,让我们只需要专注开发即可,其余的代码提交,构建镜像、推送镜像、拉取镜像、部署项目等等一切均可由Buddy来完成。

首先,点击此处免费注册一个Buddy帐户 >>>

完成注册Buddy帐户之后,登陆进入帐户。接下来,开启我们的DevOps开发运维一体化之路!

创建项目、流水线与添加操作

登陆Buddy帐户之后,点击新建项目按钮进入项目创建第一步:

Docker全方位攻略与自动化运维

选择系统自带Git托管作为项目存储仓,输入项目名称并点击新建项目按钮进行项目创建:

Docker全方位攻略与自动化运维

在此,我们将使用一个开源项目作为演示,此为基于Rust语言、使用Angular作为前端、PostgreSQL数据库的一个项目。请点击此处从GitHub下载Repo并提交推送至刚刚创建的项目存储仓之中:

Docker全方位攻略与自动化运维

点击流水线并新建一条流水线,触发器选择事件,也就是自动触发,当我们提交并推送代码至此项目存储仓时,将会自动触发并运行流水线上的操作:

Docker全方位攻略与自动化运维

在流水线上添加操作,进入流水线点击操作标签页,然后点击 + 加号按钮进一步添加操作:

Docker全方位攻略与自动化运维

我们将添加两个操作;一个是用于构建镜像,另一个用于推送镜像至私有Docker注册中心:

Docker全方位攻略与自动化运维

而在项目存储仓中有四个镜像可供我们构建:data目录下的数据库、services目录下相关后端API、www目录之下的Angular前端以及调试使用Swagger。下面,除了Swagger,我们将逐个通过构建与推送镜像操作将其余三个构建并推送至以上创建的私有注册中心之中。

数据库镜像

点击 + 加号按钮添加构建镜像,并选择如下图data目录下的Dockerfile文件,同时选择与至匹配的相关联环境,也就是data目录。然后点击蓝色按钮添加此操作:

Docker全方位攻略与自动化运维

点击 + 加号按钮添加推送镜像

Docker全方位攻略与自动化运维

举一反三,同上添加剩余的两个操作,我们就可以看到如下图在流水线上添加了总共六个操作。操作分别为构建与推送镜像:数据库、API与前端:

Docker全方位攻略与自动化运维

至此,我们的自动化运维布局已就绪!下面我们来运行这条流水线。

运行流水线构建和推送镜像

目前,在此项目中,我们可以通过两种方式运行流水线:第一种直接手动点击流水线上的运行按钮执行运行:

Docker全方位攻略与自动化运维

第二种是通过在项目中提交并推送代码至存储仓自动触发流水线执行运行。

Docker全方位攻略与自动化运维

流水线运行之后,打开浏览器并输入https://your-domain/v2/_catalog并在弹出的登陆框输入帐户信息,我们就可以在私有Docker注册中心看到如下图的相关镜像信息:

Docker全方位攻略与自动化运维

请注意更换 your-domain 为您自己的域名名称!

此时,我们的Docker项目就能够完美地与自动化运维相结合。您可以随意推送、拉取镜像来进一步开发您的项目!

总结

总结就留给您自己写吧!当您认真阅读这篇文章时,我相信您已经对Docker有了更深的认识与如何更熟练地运用。如果到这里还不知所措,那么请按照本文内容一步步进行实际操作。