糖醋鱼的小破站

🐟生成长记

什么都明白的人 最温柔也最冷漠
你一定要记得 别让一直温柔待你的人寒了心
我是一个不会哭的孩子,所以一直没有糖吃。
  menu
116 文章
7 评论
14016 浏览
1 当前访客
ღゝ◡╹)ノ❤️

Docker 学习第二部分——Containers(容器)

Get Started, Part 2: Containers

1 先决条件

  • 您已经安装了 1.13 或者版本更高的 Docker 应用程序
  • 你已经将 Docker 学习第一部分 阅读完毕
  • 为您的环境提供快速测试运行,以确保您已全部设置:
docker run hello-world

2 介绍

现在该开始以 Docker 方式构建应用程序了。我们将从这样一个应用程序的层次结构的底部开始,该应用程序是一个容器,我们将在此页面中进行介绍。在该级别之上是服务,该服务定义了容器在生产中的行为方式,在第 3 部分中进行了介绍。最后,在顶层是堆栈,定义了第 5 部分中介绍的所有服务的交互。

  • Stack
  • Services
  • Container (you are here)

3 您的新开发环境

过去,如果您要开始编写 Python 应用程序,那么首先要做的就是将 Python 运行时安装到计算机上。但是,这会造成一种情况,您的计算机上的环境必须如此,以便您的应用程序按预期运行;运行您的应用程序的服务器的同上。

使用 Docker,您只需获取一个可移植的 Python 运行时作为映像,而无需安装。然后,您的构建可以在应用程序代码的旁边包含基本的 Python 映像,以确保您的应用程序,其依赖项和运行时都一起运行。

这些可移植映像由称为 Dockerfile 的东西定义。

4 用 Dockerfile 定义一个容器

Dockerfile 将定义容器内部环境中发生的事情。在这种环境内虚拟化了对网络接口和磁盘驱动器等资源的访问,该环境与系统的其余部分隔离,因此您必须将端口映射到外部环境,并具体说明那个环境中要“复制”的文件。但是,这样做之后,您可以期望在此 Dockerfile 中定义的应用程序构建无论在任何地方运行都将表现完全相同。

4.1 Dockerfile

创建一个空目录。并进入到新目录,创建一个名为 Dockerfile 的文件,将以下内容复制并粘贴到该文件中,然后保存。请注意理解你的新 Dockerfile 中每个语句的注释。

# Use an official Python runtime as a parent image
FROM python:2.7-slim

# Set the working directory to /app
WORKDIR /app

# Copy the current directory contents into the container at /app
ADD . /app

# Install any needed packages specified in requirements.txt
RUN pip install --trusted-host pypi.python.org -r requirements.txt

# Make port 80 available to the world outside this container
EXPOSE 80

# Define environment variable
ENV NAME World

# Run app.py when the container launches
CMD ["python", "app.py"]

Are you behind a proxy server?
代理服务器可以在您的网络应用启动并运行后立即阻止其连接。如果您位于代理服务器后面,请使用 ENV 命令为您的 Dockerfile 添加以下行,以指定代理服务器的主机和端口:

# Set proxy server, replace host:port with values for your servers
ENV http_proxy host:port
ENV https_proxy host:port

在调用 pip 之前添加这些行,以使安装成功。

这个 Dockerfile 指向了我们尚未创建的几个文件,即 app.pyrequirements.txt 。接下来创建这些。

5 应用本身

再创建两个文件 requirements.txtapp.py,并将它们与 Dockerfile 放在同一文件夹中。这样就完成了我们的应用程序,您可以看到它非常简单。当上述 Dockerfile 内置到映像中时,由于该 DockerfileADD 命令,将显示 app.pyrequirements.txt,并且借助 EXPOSE 命令,可以通过 HTTP 访问 app.py 的输出。

5.1 requirements.txt

Flask
Redis

5.2 app.py

from flask import Flask
from redis import Redis, RedisError
import os
import socket

# Connect to Redis
redis = Redis(host="redis", db=0, socket_connect_timeout=2, socket_timeout=2)

app = Flask(__name__)

@app.route("/")
def hello():
    try:
        visits = redis.incr("counter")
    except RedisError:
        visits = "<i>cannot connect to Redis, counter disabled</i>"

    html = "<h3>Hello {name}!</h3>" \
           "<b>Hostname:</b> {hostname}<br/>" \
           "<b>Visits:</b> {visits}"
    return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname(), visits=visits)

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=80)

现在,我们看到 pip install -r requirements.txt 安装了 Python 的 Flask 和 Redis 库,并且该应用程序打印了环境变量 NAME 以及对 socket.gethostname() 的调用的输出。最后,由于 Redis 没有运行(因为我们仅安装了 Python 库,而没有安装 Redis 本身),因此我们应该期望在此处使用它的尝试会失败并产生错误消息。

注意:在容器内访问主机名将检索容器 ID,这类似于正在运行的可执行文件的进程 ID。

这就是神奇的地方!您无需在系统上使用 Python 或 Requirements.txt 中的任何内容,也无需构建或运行此映像即可在系统上安装它们。似乎您并没有真正使用 Python 和 Flask 设置环境,但是已经有了。

5.3 Build the app

我们准备构建该应用程序。确保您仍在新目录的顶层。 使用 ls 命令应该显示以下内容:

$ ls
Dockerfile		app.py			requirements.txt

现在运行 build 命令。这将创建一个 Docker 映像,我们将使用 -t 对其进行标记,给他起一个友好的名字。

docker build -t friendlyhello .

你构建的 images 在哪里呢?它位于计算机的本地 Docker 映像注册表中:

$ docker images

REPOSITORY            TAG                 IMAGE ID
friendlyhello         latest              326387cea398

5.4 Run the app

运行应用,使用 -p 将计算机的端口 4000 映射到容器的已发布端口 80:

docker run -p 4000:80 friendlyhello

您应该在 http://0.0.0.0:80 看到一条消息,指出 Python 正在为您的应用提供服务。但是该消息是从容器内部发出的,它不知道您已将该容器的端口 80 映射到 4000,从而生成了正确的 URL http://localhost:4000

在网络浏览器中转到该 URL,以查看网页上提供的显示内容。

Hello World in browser

注意:如果您在 Windows 7 上使用 Docker Toolbox,请使用 Docker Machine IP 代替 localhost。例如,http://192.168.99.100:4000/。要找到 IP 地址,请使用命令 docker-machine ip

您也可以在 shell 程序中使用 curl 命令查看相同的内容。

$ curl http://localhost:4000

<h3>Hello World!</h3><b>Hostname:</b> 8fc990912a14<br/><b>Visits:</b> <i>cannot connect to Redis, counter disabled</i>

此端口重新映射为 4000:80,目的是演示 Dockerfile 中的 EXPOSE 内容与使用 docker run -p 发布的内容之间的区别。在后面的步骤中,我们将主机上的端口 80 映射到容器中的端口 80,并使用 http:// localhost

在终端中按 CTRL + C 退出。

在 Windows 上,明确停止容器在 Windows 系统上,CTRL + C 不会停止容器。因此,首先键入 CTRL + C 以返回提示(或打开另一个 shell),然后键入 docker container ls 列出正在运行的容器,然后键入 docker container stop 容器名称或 ID 来停止容器。否则,当您尝试在下一步中重新运行容器时,将从守护程序中收到错误响应。

现在,让我们以分离模式在后台运行该应用:

docker run -d -p 4000:80 friendlyhello

您将获得应用程序的长容器 ID,然后将其踢回终端。您的容器在后台运行。您还可以看到带有 docker container ls 的缩写容器 ID(并且在运行命令时两者可以互换使用):

$ docker container ls
CONTAINER ID        IMAGE               COMMAND             CREATED
1fa4ab2cf395        friendlyhello       "python app.py"     28 seconds ago

您会看到 CONTAINER ID 与 http:// localhost:4000上的内容匹配。现在使用docker container stop 通过容器 ID 结束进程,如下所示:

docker container stop 1fa4ab2cf395

5.5 Share your image

为了演示我们刚刚创建的图像的可移植性,让我们上传构建的图像并在其他地方运行它。毕竟,当您要将容器部署到生产环境时,您将需要学习如何推送到注册表。

注册表是存储库的集合,而存储库是图像的集合,类似于 GitHub 存储库,只是已经构建了代码。注册表上的帐户可以创建许多存储库。 Docker CLI 默认使用 Docker 的公共注册表。

注意:我们将在这里使用 Docker 的公共注册表是因为它是免费的且已预先配置,但有许多公共选项可供选择,您甚至可以使用 Docker Trusted Registry 设置自己的私有注册表。

5.5.1 Log in with your Docker ID

如果您没有 Docker 帐户,请在https://cloud.docker.com/上注册一个。记下您的用户名。

登录到本地计算机上的 Docker 公共注册表。

$ docker login

5.5.2 Tag the image

用于将本地映像与注册表上的存储库关联的表示法是 username/repository:tag。该标签是可选的,但值得推荐,因为它是注册管理机构用来给 Docker 映像提供版本的机制。给存储库命名并为上下文标记有意义的名称,例如 get-started:part2。这会将 get-started 存储库中,并将其标记为 part2

现在,将它们放在一起以标记图像。使用您的用户名,存储库和标签名称运行 docker tag image,以便该图像将上传到您所需的目的地。该命令的语法为:

docker tag image username/repository:tag

For example:

docker tag friendlyhello john/get-started:part2

运行 docker images 以查看新标记的图像。(您也可以使用 docker images ls)。

$ docker images
REPOSITORY               TAG                 IMAGE ID            CREATED             SIZE
friendlyhello            latest              d9e555c53008        3 minutes ago       195MB
john/get-started         part2               d9e555c53008        3 minutes ago       195MB
python                   2.7-slim            1c7128a655f6        5 days ago          183MB
...

5.5.3 Publish the image

将您标记的图像上传到存储库:

docker push username/repository:tag

完成后,此上载的结果将公开提供。如果登录到 Docker 中心,您将看到新映像及其拉取命令。

5.5.4 从远程存储库中提取并运行映像

从现在开始,您可以使用 docker run 并通过以下命令在任何计算机上运行您的应用程序:

docker run -p 4000:80 username/repository:tag

如果该映像在计算机上本地不可用,则 Docker 将从存储库中提取该映像。

$ docker run -p 4000:80 john/get-started:part2
Unable to find image 'john/get-started:part2' locally
part2: Pulling from john/get-started
10a267c67f42: Already exists
f68a39a6a5e4: Already exists
9beaffc0cf19: Already exists
3c1fe835fb6b: Already exists
4c9f1fa8fcb8: Already exists
ee7d8f576a14: Already exists
fbccdcced46e: Already exists
Digest: sha256:0601c866aab2adcc6498200efd0f754037e909e5fd42069adeff72d1e2439068
Status: Downloaded newer image for john/get-started:part2
 * Running on http://0.0.0.0:80/ (Press CTRL+C to quit)

无论 docker run 在何处执行,它都会将您的映像以及 Python 和所有来自 requirements.txt 的依赖项拉出,并运行您的代码。所有这些都以整齐的小包装一起运送,并且主机无需安装任何东西即可运行,Docker 除外。

6 第二部分总结

仅此页而已。在下一节中,我们将学习如何通过在服务中运行此容器来扩展应用程序。

仅此页而已。在下一节中,我们将学习如何通过在服务中运行此容器来扩展应用程序。

7 总结和备忘单(可选)

这是此页面所涵盖内容的终端记录

这是此页面上的基本 Docker 命令的列表,以及一些相关的命令(如果您想在继续之前进行一些探索)。

docker build -t friendlyname .  # Create image using this directory's Dockerfile
docker run -p 4000:80 friendlyname  # Run "friendlyname" mapping port 4000 to 80
docker run -d -p 4000:80 friendlyname         # Same thing, but in detached mode
docker container ls                                # List all running containers
docker container ls -a             # List all containers, even those not running
docker container stop <hash>           # Gracefully stop the specified container
docker container kill <hash>         # Force shutdown of the specified container
docker container rm <hash>        # Remove specified container from this machine
docker container rm $(docker container ls -a -q)         # Remove all containers
docker image ls -a                             # List all images on this machine
docker image rm <image id>            # Remove specified image from this machine
docker image rm $(docker image ls -a -q)   # Remove all images from this machine
docker login             # Log in this CLI session using your Docker credentials
docker tag <image> username/repository:tag  # Tag <image> for upload to registry
docker push username/repository:tag            # Upload tagged image to registry
docker run username/repository:tag                   # Run image from a registry


标题:Docker 学习第二部分——Containers(容器)
作者:expoli
地址:https://expoli.tech/articles/2019/09/22/1569142374417.html

评论