将图像作为容器运行
预计阅读时间:10分钟
先决条件
在“构建节点图像”中逐步完成构建Node JS图像的步骤。
概述
在上一个模块中,我们创建了示例应用程序,然后创建了用于创建映像的Dockerfile。我们使用命令创建了图像docker build
。现在我们有了一个映像,我们可以运行该映像,并查看我们的应用程序是否正常运行。
容器是正常的操作系统进程,除了该进程是隔离的,并且具有与主机分开的其自己的文件系统,其网络和其独立的进程树。
要在容器内运行图像,请使用docker run
命令。该docker run
命令需要一个参数,即图像名称。让我们开始映像,并确保其正确运行。在终端中执行以下命令。
$ docker run node-docker
运行此命令时,您会注意到您没有返回到命令提示符。这是因为我们的应用程序是REST服务器,并且将在循环中运行以等待传入的请求,而不会将控制权返回给OS,直到我们停止容器为止。
让我们打开一个新终端,然后使用curl命令向服务器发出GET请求。
$ curl --request POST \
--url http://localhost:8000/test \
--header 'content-type: application/json' \
--data '{
"msg": "testing"
}'
curl: (7) Failed to connect to localhost port 8000: Connection refused
我们的curl命令失败,因为与服务器的连接被拒绝。这意味着我们无法在端口8000上连接到localhost。这是可以预期的,因为我们的容器是独立运行的,其中包括网络。让我们停止容器,然后使用在本地网络上发布的端口8000重新启动。
要停止容器,请按ctrl-c。这将使您返回到终端提示。
要为我们的容器发布端口,我们将在docker run命令上使用--publish
标志(-p
简称)。该--publish
命令的格式为[host port]:[container port]
。因此,如果我们想将容器内部的端口8000暴露给容器外部的端口3000,则可以将3000:8000传递给--publish标志。
启动容器,并将端口8000暴露给主机上的端口8000。
$ docker run --publish 8000:8000 node-docker
现在,让我们从上方重新运行curl命令。记住要打开一个新终端。
$ curl --request POST \
--url http://localhost:8000/test \
--header 'content-type: application/json' \
--data '{"msg": "testing"}'
{"code":"success","payload":[{"msg":"testing","id":"dc0e2c2b-793d-433c-8645-b3a553ea26de","createDate":"2020-09-01T17:36:09.897Z"}]}
成功!我们能够连接到在端口8000上的容器内部运行的应用程序。切换回容器正在运行的终端,您应该看到POST请求已记录到控制台。
2020-09-01T17:36:09:8770 INFO: POST /test
按ctrl-c停止容器。
以分离模式运行
到目前为止,这很好,但是我们的示例应用程序是Web服务器,我们不必将终端连接到容器。Docker可以以分离模式或在后台运行您的容器。为此,我们可以使用--detach
或-d
简称。Docker将以与以前相同的方式启动您的容器,但是这次将“与容器分离”,并返回到终端提示符。
$ docker run -d -p 8000:8000 node-docker
ce02b3179f0f10085db9edfccd731101868f58631bdf918ca490ff6fd223a93b
Docker在后台启动了我们的容器,并在终端上打印了容器ID。
再次,让我们确保我们的容器运行正常。从上方运行相同的curl命令。
$ curl --request POST \
--url http://localhost:8000/test \
--header 'content-type: application/json' \
--data '{
"msg": "testing"
}'
{"code":"success","payload":[{"msg":"testing","id":"dc0e2c2b-793d-433c-8645-b3a553ea26de","createDate":"2020-09-01T17:36:09.897Z"}]}
列出容器
由于我们在后台运行容器,因此我们如何知道容器是否正在运行或机器上还运行了其他哪些容器?好了,我们可以运行docker ps
命令了。就像在Linux上一样,要查看您机器上的进程列表,我们将运行ps命令。本着同样的精神,我们可以运行docker ps
命令,该命令将向我们显示在计算机上运行的容器的列表。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ce02b3179f0f node-docker "docker-entrypoint.s…" 6 minutes ago Up 6 minutes 0.0.0.0:8000->8000/tcp wonderful_kalam
该ps
命令告诉了我们有关正在运行的容器的大量信息。我们可以看到“容器ID”,“容器中运行的映像”,用于启动容器的命令,创建时的状态,状态,暴露的端口以及容器的名称。
您可能想知道我们容器的名称来自何处。由于启动时我们没有为容器提供名称,因此Docker生成了一个随机名称。我们将在一分钟内解决此问题,但首先我们需要停止该容器。要停止容器,请运行执行该docker stop
命令的命令,即停止容器。您将需要传递容器的名称,也可以使用容器的ID。
$ docker stop wonderful_kalam
wonderful_kalam
现在,重新运行docker ps
命令以查看正在运行的容器的列表。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
停止,启动和命名容器
可以启动,停止和重新启动Docker容器。当我们停止容器时,它不会被删除,但是状态会更改为已停止,并且容器内部的进程也会停止。当我们运行docker ps
命令时,默认输出是仅显示正在运行的容器。如果我们通过--all
或-a
简称,我们将在系统上看到所有容器,无论它们是停止还是启动。
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ce02b3179f0f node-docker "docker-entrypoint.s…" 16 minutes ago Exited (0) 5 minutes ago wonderful_kalam
ec45285c456d node-docker "docker-entrypoint.s…" 28 minutes ago Exited (0) 20 minutes ago agitated_moser
fb7a41809e5d node-docker "docker-entrypoint.s…" 37 minutes ago Exited (0) 36 minutes ago goofy_khayyam
如果您一直在关注,您应该会看到列出的几个容器。这些是我们启动和停止但尚未删除的容器。
让我们重新启动刚刚停止的容器。找到我们刚刚停止的容器的名称,然后在重新启动命令中替换下面的容器的名称。
$ docker restart wonderful_kalam
现在,使用ps命令再次列出所有容器。
$ docker ps --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ce02b3179f0f node-docker "docker-entrypoint.s…" 19 minutes ago Up 8 seconds 0.0.0.0:8000->8000/tcp wonderful_kalam
ec45285c456d node-docker "docker-entrypoint.s…" 31 minutes ago Exited (0) 23 minutes ago agitated_moser
fb7a41809e5d node-docker "docker-entrypoint.s…" 40 minutes ago Exited (0) 39 minutes ago goofy_khayyam
请注意,我们刚刚重新启动的容器已经以分离模式启动,并且暴露了端口8000。另外,观察容器的状态为“ Up X seconds”。重新启动容器时,将使用与最初启动时相同的标志或命令来启动它。
让我们停下来并移除所有容器,看看如何解决随机命名问题。
停止我们刚刚开始的容器。查找正在运行的容器的名称,然后将以下命令中的名称替换为系统上容器的名称。
$ docker stop wonderful_kalam
wonderful_kalam
现在我们所有的容器都停止了,让我们删除它们。删除容器后,它将不再运行,也不会处于停止状态。但是,容器内部的过程已停止,并且容器的元数据已被删除。
$ docker ps --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ce02b3179f0f node-docker "docker-entrypoint.s…" 19 minutes ago Up 8 seconds 0.0.0.0:8000->8000/tcp wonderful_kalam
ec45285c456d node-docker "docker-entrypoint.s…" 31 minutes ago Exited (0) 23 minutes ago agitated_moser
fb7a41809e5d node-docker "docker-entrypoint.s…" 40 minutes ago Exited (0) 39 minutes ago goofy_khayyam
要删除容器,只需运行docker rm
传递容器名称的命令即可。您可以在一个命令中将多个容器名称传递给该命令。
同样,请确保将以下命令中的容器名称替换为系统中的容器名称。
$ docker rm wonderful_kalam agitated_moser goofy_khayyam
wonderful_kalam
agitated_moser
goofy_khayyam
docker ps --all
再次运行命令以查看所有容器都已消失。
现在让我们解决讨厌的随机名称问题。标准做法是为容器命名,原因很简单,因为它易于识别容器中正在运行的内容以及与之关联的应用程序或服务。就像代码中对变量的良好命名约定一样,它使读取更容易。因此,命名您的容器。
要命名容器,我们只需要将--name
标志传递给run命令即可。
$ docker run -d -p 8000:8000 --name rest-server node-docker
1aa5d46418a68705c81782a58456a4ccdb56a309cb5e6bd399478d01eaa5cdda
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1aa5d46418a6 node-docker "docker-entrypoint.s…" 3 seconds ago Up 3 seconds 0.0.0.0:8000->8000/tcp rest-server
现在,我们可以根据名称轻松识别容器。
下一步
在本模块中,我们研究了运行容器,发布端口以及以分离模式运行容器。我们还介绍了如何通过启动,停止和重新启动容器来管理容器。我们还研究了命名容器的方式,以便更容易识别它们。在下一个模块中,我们将学习如何在容器中运行数据库并将其连接到我们的应用程序。看:
反馈
通过提供您的反馈帮助我们改善此主题。通过在Docker Docs GitHub存储库中创建问题,让我们知道您的想法。或者,创建PR以建议更新。