将您的 Go 镜像作为容器运行
先决条件
请按照构建您的 Go 镜像中的步骤,将 Go 应用程序容器化。
概述
在上一模块中,您为示例应用程序创建了一个 `Dockerfile`,然后使用 `docker build` 命令创建了 Docker 镜像。现在您有了镜像,可以运行该镜像并查看应用程序是否正常运行。
容器是一个正常的操作系统进程,只不过此进程是隔离的,拥有自己的文件系统、自己的网络和与主机分离的独立进程树。
要在容器内运行镜像,请使用 `docker run` 命令。它需要一个参数,即镜像名称。启动您的镜像并确保其正常运行。在终端中运行以下命令。
$ docker run docker-gs-ping
____ __
/ __/___/ / ___
/ _// __/ _ \/ _ \
/___/\__/_//_/\___/ v4.10.2
High performance, minimalist Go web framework
https://echo.labstack.com
____________________________________O/_______
O\
⇨ http server started on [::]:8080当您运行此命令时,会注意到您没有返回到命令提示符。这是因为您的应用程序是一个 REST 服务器,它将在循环中运行,等待传入请求,直到您停止容器,否则不会将控制权返回给操作系统。
使用 curl 命令向服务器发出 GET 请求。
$ curl https://:8080/
curl: (7) Failed to connect to localhost port 8080: Connection refused
您的 curl 命令失败了,因为与服务器的连接被拒绝。这意味着您无法连接到 localhost 的 8080 端口。这是预料之中的,因为您的容器在隔离环境中运行,其中包含网络。停止容器并重新启动,将 8080 端口发布到您的本地网络。
要停止容器,请按 ctrl-c。这会将您返回到终端提示符。
要为容器发布端口,您将在 `docker run` 命令中使用 `--publish` 标志(简写为 `-p`)。`--publish` 命令的格式为 `[host_port]:[container_port]`。因此,如果您想将容器内的 `8080` 端口暴露给容器外的 `3000` 端口,您可以将 `3000:8080` 传递给 `--publish` 标志。
启动容器并将容器的 `8080` 端口暴露给主机的 `8080` 端口。
$ docker run --publish 8080:8080 docker-gs-ping
现在,重新运行 curl 命令。
$ curl https://:8080/
Hello, Docker! <3
成功了!您已经能够连接到在容器内运行的应用程序的 8080 端口。切换回您的容器正在运行的终端,您应该会看到 `GET` 请求已记录到控制台。
按 `ctrl-c` 停止容器。
在分离模式下运行
目前为止一切顺利,但您的示例应用程序是一个 Web 服务器,您不应该将终端连接到容器。Docker 可以在后台以分离模式运行您的容器。为此,您可以使用 `--detach` 或简写为 `-d`。Docker 将像以前一样启动您的容器,但这次将与容器分离并返回到终端提示符。
$ docker run -d -p 8080:8080 docker-gs-ping
d75e61fcad1e0c0eca69a3f767be6ba28a66625ce4dc42201a8a323e8313c14e
Docker 在后台启动了您的容器,并在终端上打印了容器 ID。
再次确认您的容器正在运行。运行相同的 `curl` 命令。
$ curl https://:8080/
Hello, Docker! <3
列出容器
既然您在后台运行了容器,如何知道您的容器是否正在运行,或者您的机器上还有哪些其他容器正在运行?要查看机器上正在运行的容器列表,请运行 `docker ps`。这类似于 `ps` 命令在 Linux 机器上用于查看进程列表的方式。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d75e61fcad1e docker-gs-ping "/docker-gs-ping" 41 seconds ago Up 40 seconds 0.0.0.0:8080->8080/tcp inspiring_ishizaka
`ps` 命令会告诉您有关正在运行的容器的许多信息。您可以看到容器 ID、容器内运行的镜像、用于启动容器的命令、创建时间、状态、暴露的端口以及容器的名称。
您可能想知道容器的名称从何而来。由于您在启动容器时没有提供名称,Docker 生成了一个随机名称。我们稍后会解决这个问题,但首先您需要停止容器。要停止容器,请运行 `docker stop` 命令,并传入容器的名称或 ID。
$ docker stop inspiring_ishizaka
inspiring_ishizaka
现在重新运行 `docker ps` 命令,查看正在运行的容器列表。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
停止、启动和命名容器
Docker 容器可以启动、停止和重新启动。当您停止一个容器时,它并没有被移除,只是状态变为停止,并且容器内的进程也停止了。当您运行 `docker ps` 命令时,默认输出只显示正在运行的容器。如果您传递 `--all` 或简写为 `-a`,您将看到系统上的所有容器,包括已停止的容器和正在运行的容器。
$ docker ps --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d75e61fcad1e docker-gs-ping "/docker-gs-ping" About a minute ago Exited (2) 23 seconds ago inspiring_ishizaka
f65dbbb9a548 docker-gs-ping "/docker-gs-ping" 3 minutes ago Exited (2) 2 minutes ago wizardly_joliot
aade1bf3d330 docker-gs-ping "/docker-gs-ping" 3 minutes ago Exited (2) 3 minutes ago magical_carson
52d5ce3c15f0 docker-gs-ping "/docker-gs-ping" 9 minutes ago Exited (2) 3 minutes ago gifted_mestorf
如果您一直跟着操作,您应该会看到列出了几个容器。这些是您启动并停止但尚未移除的容器。
重新启动您刚刚停止的容器。找到容器的名称,并用您系统上容器的名称替换以下 `restart` 命令中的容器名称。
$ docker restart inspiring_ishizaka
现在,再次使用 `ps` 命令列出所有容器
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d75e61fcad1e docker-gs-ping "/docker-gs-ping" 2 minutes ago Up 5 seconds 0.0.0.0:8080->8080/tcp inspiring_ishizaka
f65dbbb9a548 docker-gs-ping "/docker-gs-ping" 4 minutes ago Exited (2) 2 minutes ago wizardly_joliot
aade1bf3d330 docker-gs-ping "/docker-gs-ping" 4 minutes ago Exited (2) 4 minutes ago magical_carson
52d5ce3c15f0 docker-gs-ping "/docker-gs-ping" 10 minutes ago Exited (2) 4 minutes ago gifted_mestorf
请注意,您刚刚重新启动的容器已在分离模式下启动,并暴露了 8080 端口。另外,请注意容器的状态是 `Up X seconds`。当您重新启动容器时,它将使用最初启动时使用的相同标志或命令来启动。
停止并移除所有容器,然后看看如何解决随机命名问题。
停止您刚刚启动的容器。找到您正在运行的容器的名称,并用您系统上容器的名称替换以下命令中的名称。
$ docker stop inspiring_ishizaka
inspiring_ishizaka
既然您的所有容器都已停止,请将其移除。当容器被移除时,它不再运行,也不处于停止状态。相反,容器内的进程被终止,容器的元数据被移除。
要移除容器,请运行 `docker rm` 命令,并传入容器名称。您可以在一个命令中向该命令传递多个容器名称。
再次强调,请务必将以下命令中的容器名称替换为您系统中的容器名称。
$ docker rm inspiring_ishizaka wizardly_joliot magical_carson gifted_mestorf
inspiring_ishizaka
wizardly_joliot
magical_carson
gifted_mestorf
再次运行 `docker ps --all` 命令以验证所有容器都已消失。
现在,解决恼人的随机命名问题。标准做法是为容器命名,原因很简单:更容易识别容器中运行的内容以及它与哪个应用程序或服务相关联。就像您代码中变量的良好命名约定使其更易于阅读一样,容器命名也遵循同样的道理。
要命名容器,您必须将 `--name` 标志传递给 `run` 命令
$ docker run -d -p 8080:8080 --name rest-server docker-gs-ping
3bbc6a3102ea368c8b966e1878a5ea9b1fc61187afaac1276c41db22e4b7f48f
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3bbc6a3102ea docker-gs-ping "/docker-gs-ping" 25 seconds ago Up 24 seconds 0.0.0.0:8080->8080/tcp rest-server
现在,您可以根据名称轻松识别您的容器。
后续步骤
在本模块中,您学习了如何运行容器和发布端口。您还学习了如何管理容器的生命周期。然后,您了解了为容器命名的重要性,以便它们更容易识别。在下一模块中,您将学习如何在容器中运行数据库并将其连接到您的应用程序。