type
Post
status
Published
date
Sep 22, 2019
slug
2019/09/22/1569138739065
summary
Docker 学习第一部分——Orientation and setup
tags
Docker
category
Docker
created days
new update day
icon
password
Created_time
Dec 5, 2022 09:05 AM
Last edited time
Mar 1, 2025 01:50 AM
Part 1: Orientation and setup
欢迎!我们很高兴您想学习如何使用Docker。
在这个由六部分组成的教程中,您将学习:
- 在此页面上做好准备并确定学习方向
- 构建并运行您的第一个应用将您的应用
- 将应用转换为缩放服务
- 将服务跨多台计算机
- 添加可保留数据的访客计数器
- 将您的集群部署到生产
1.1 先决条件
虽然我们将在此过程中定义概念,但最好在开始之前了解 Docker 是什么以及为什么使用 Docker。
在继续之前,我们还需要假定您熟悉一些概念:
- IP地址和端口
- 虚拟机
- 编辑配置文件
- 基本了解代码依赖关系和构建的思想
- 机器资源使用条件,例如CPU百分比,以字节为单位的RAM使用率等。
最后,尽管我们会在需要这些东西时再次提醒您,但是您可以通过注册Docker ID并运行以下命令在本地计算机上使用它,从而节省一些时间:
docker login
1.2 容器的简要说明
映像(image)是一个轻量级的,独立的,可执行的程序包,其中包含运行某个软件所需的一切,包括代码,运行时,库,环境变量和配置文件。
容器(container)是映像的运行时实例,即映像在实际执行时在内存中的位置。默认情况下,它与主机环境完全隔离运行,仅访问主机文件和端口(如果需要这样做配置)。
容器在主机的内核上本机运行应用。与仅通过虚拟机管理程序虚拟访问主机资源的虚拟机相比,它们具有更好的性能特征。容器可以获取本机访问,每个访问都运行在离散进程中,占用的内存不会比任何其他可执行文件多。
1.3 容器 vs 虚拟机
考虑下图比较虚拟机和容器:
1.3.1 虚拟机图
虚拟机运行来宾操作系统 — 请注意每个框中的操作系统层。这是资源密集型的,生成的磁盘映像和应用程序状态是操作系统设置、系统安装的依赖项、操作系统安全修补程序和其他容易丢失、难以复制的应用程序状态。
1.3.2 容器图
容器可以共享一个内核,并且唯一需要包含在容器映像中的信息是可执行文件及其与程序包的依赖关系,而这些信息永远不需要安装在主机系统上。这些进程像本机进程一样运行,您可以通过运行docker ps等命令来单独管理它们-就像在Linux上运行ps来查看活动进程一样。最后,由于它们包含所有依赖关系,因此没有配置纠缠;容器化的应用程序“可在任何地方运行”。
2 Setup
在开始之前,请确保您的系统已安装了最新版本的Docker。
Note: version 1.13 or higher is required
您应该能够运行docker run hello-world并看到如下响应:
Note:您可能需要将用户添加到docker 组中,才能在不使用sudo的情况下调用此命令。[阅读更多](https://docs.docker.com/v17.09/engine/installation/linux/linux-postinstall/
Note:如果您的设置中存在网络问题,则 docker run hello-world 可能无法成功执行。如果您位于代理服务器后面,并且怀疑它阻止了连接,请检查本教程的下一部分。
$ docker run hello-world Hello from Docker! This message shows that your installation appears to be working correctly. To generate this message, Docker took the following steps: ...(snipped)...
现在也是确认您使用的是不是1.13版或更高版本Docker的好时机。运行
docker --version
进行检查。$ docker --version Docker version 17.05.0-ce-rc1, build 2878a85
如果您看到上述信息,则可以开始您的旅程了。
3. 结论
规模单位是一个单独的、可移植的可执行文件,具有巨大的意义。这意味着 CI\/CD 可以将更新推送到分布式应用程序的任何部分,系统依赖项不是问题,并且资源密度会增加。缩放行为的编排是启动新可执行文件的问题,而不是新的 VM 主机。
我们将学习所有这些事情,但是首先我们需要先学会走路。
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.py
和 requirements.txt
。接下来创建这些。5 应用本身
再创建两个文件
requirements.txt
和 app.py
,并将它们与 Dockerfile
放在同一文件夹中。这样就完成了我们的应用程序,您可以看到它非常简单。当上述 Dockerfile
内置到映像中时,由于该 Dockerfile
的 ADD
命令,将显示 app.py
和 requirements.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,以查看网页上提供的显示内容。

注意:如果您在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
欢迎加入“喵星计算机技术研究院”,原创技术文章第一时间推送。

- 作者:tangcuyu
- 链接:https://expoli.tech/articles/2019/09/22/1569138739065
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
相关文章