docker 入门2 - 容器 【翻译】
入门,第 2 部分:容器
先决条件
- 安装的 Docker 版本是 1.13 及以上。
- 读完 第一部分
用下面的命令快速测试你的环境是否完备:
docker run hello-world
概述
现在开始用 Docker 的方式构建应用。我们从这个应用的层次结构底部开始,也就是这里讲的容器。在容器层上面有第三部分讲的 service 层,定义了生产中的容器的行为方式。最顶层的是第五部分讲的 stack 层,定义了所有 service 的交互。
- Stack
- Services
- Container (你在这里)
新的部署环境
过去,如果要写个 Python 应用,首先要在机器上安装 Python 运行时。这就带来了一个问题:要使应用按照预期运行,就需要机器上的环境完美适合应用程序,同时生产环境需要与开发环境完全一致。
通过 Docker,可以将一个可移植的 Python 运行时作为一个 image 镜像获取,无需安装。 然后,构建时可以将基础 Python 镜像与应用程序代码一起包括在内,确保应用程序,依赖项和运行时都一起发布。 通过 Dockerfile 定义可移植的镜像。
用Dockerfile定义一个容器
Dockerfile 定义了容器中的环境包含哪些东西。对网络接口、磁盘等资源的访问被虚拟化到了这个环境内部,从而与系统的其他部分隔离,因此必须映射端口到外部,并且指明需要把哪些文件复制到容器内部。这些完成后,通过这个 Dockerfile 对应用的构建在任何地方运行时都会有相同的表现。
Dockerfile
在本地计算机上创建空目录。改变目录 (cd) 进入到新目录,创建名为 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
COPY . /app # Install any needed packages specified in requirements.txt
RUN pip install --trusted-host pypi.python.org -r requirements.txt # Make port available to the world outside this container
EXPOSE # Define environment variable
ENV NAME World # Run app.py when the container launches
CMD ["python", "app.py"]
此 Dockerfile 是指一些尚未创建的文件,即app.py和requirements.txt。接下来,让我们创建这些。
应用程序本身
再创建两个文件,requirements.txt 和app.py,并将它们与 Dockerfile 放在同一文件夹中。这完成了我们的应用程序,你可以看到这是很简单的。当上述 Dockerfile 内置到映像中时,由于 Dockerfile 的 COPY 命令,app.py和requirements.txt 存在,并且由于 EXPOSE命令,可以通过 HTTP 访问来自app.py的输出。
requirements.txt
Flask
Redis
app.py
from flask import Flask
from redis import Redis, RedisError
import os
import socket # Connect to Redis
redis = Redis(host="redis", db=, socket_connect_timeout=, socket_timeout=) 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=)
现在我们看到 pip install -r requirements.txt 为 Python 安装 Flask 和 Redis 库,应用程序打印环境变量 NAME 以及调用 socket.gethostname() 的输出。最后,由于 Redis 未运行(因为我们只安装了 Python 库,而不是 Redis 本身),因此,我们应预期在此处使用它的尝试失败并生成错误消息。
注意:在容器内访问主机的名称将检索容器 ID,该 ID 类似于正在运行的可执行文件的进程 ID。
就是这样!您不需要 Python 或任何requirements.txt 在您的系统上,也不构建或运行此映像安装它们在您的系统上。看起来您并没有真正使用 Python 和 Flask 建立了一个环境,但您已经设置了环境。
构建应用
我们准备构建应用程序。请确保您仍在新目录的顶层。以下是 ls 应显示的内容:
$ ls
Dockerfile app.py requirements.txt
现在运行生成命令。这将创建一个 Docker 镜像,我们将使用 --tag 选项命名该镜像。如果要使用较短的选项,请使用 -t。
docker build --tag=friendlyhello .
你的构建镜像在哪里?它位于计算机的本地 Docker 镜像注册表中:
$ docker image ls REPOSITORY TAG IMAGE ID
friendlyhello latest 326387cea398
请注意标记如何默认为最新标记。标记选项的完整语法类似于
--tag=friendlyhello:v0.0.1.
Linux 用户的故障排除
代理服务器设置
代理服务器可以在 Web 应用启动并运行后阻止其连接到该站点。如果位于代理服务器后面,请向 Dockerfile 添加以下行,使用 ENV 命令指定代理服务器的主机和端口:
# Set proxy server, replace host:port with values for your servers
ENV http_proxy host:port
ENV https_proxy host:portDNS 设置
DNS 配置错误可能会生成
pip问题。您需要设置自己的 DNS 服务器地址,以使pip正常工作。您可能需要更改 Docker 守护进程程序的 DNS 设置。您可以使用dns密钥在/etc/docker/daeon.json上编辑(或创建)配置文件,如下所示:{
"dns": ["your_dns_address", "8.8.8.8"]
}在上面的示例中,列表的第一个元素是 DNS 服务器的地址。第二个项目是谷歌的DNS,可以使用时,第一个不可用。
在继续之前,请保存
daemon.json并重新启动 docker 服务。sudo service docker restart修复后,重试以运行
build命令。
运行应用
运行应用,使用 -p 将计算机的端口 4000 映射到容器的已发布端口 80:
docker run -p : friendlyhello
您应该会看到一条消息,指出 Python 正在http://0.0.0.0:80为你的应用提供服务。但是,该消息来自容器内部,该容器不知道您将该容器的端口 80 映射到 4000,从而正确的 URL 是 http://localhost:4000。
转到 Web 浏览器中的该 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 时设置的发布值之间的差异。在后面的步骤中,将主机上的端口 4000 映射到容器中的端口 80 并使用http://localhost。
在终端中点击 CTRL+C 以退出。
在 Windows 上,显式停止容器
在 Windows 系统上,CTRL+C 不会停止容器。因此,首先键入 CTRL_C 以返回提示(或打开另一个 shell),然后键入 docker 容器 ls 以列出正在运行的容器,然后键入 docker 容器停止 [容器名称或 ID] 以停止容器。否则,当您尝试在下一步中重新运行容器时,您将从守护进程收到错误响应。
现在,让我们在后台以分离模式运行应用:
docker run -d -p : friendlyhello
您将获得应用的长容器 ID,然后被踢回终端。容器在后台运行。您还可以看到带有 docker container ls 的缩写容器 ID(在运行命令时,两者可互换):
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED
1fa4ab2cf395 friendlyhello "python app.py" seconds ago
请注意,CONTAINER ID 与http://localhost:4000上的内容相匹配。
现在使用 docker container stop 来结束进程,使用 CONTAINER ID,如下所示:
docker container stop 1fa4ab2cf395
分享镜像
为了演示我们刚刚创建的内容的可移植性,让我们上传构建的镜像并将其运行到其他地方。毕竟,您需要知道如何在将容器部署到生产时推送到registries。
一个registry是repositories的集合, repository是镜像的集合— 类似于 GitHub repository,但代码已经生成。一个registry上的帐户可以创建许多repositories。默认情况下,Docker CLI 使用 Docker 的公共registry。
注意:我们在这里使用 Docker 的公共registry,只是因为它是免费的,并且预先配置了,但有许多公共registry可供选择,您甚至可以使用 Docker 可信registry设置您自己的专用registry。
用 Docker ID 登录
如果您没有 Docker 帐户,请hub.docker.com注册。记下您的用户名。
在本地机器上登录 Docker 的公共 registry:
$ docker login
给镜像打标签(Tag)
将一个本地镜像关联到注册处 registry 中的一个仓库的符号是 username/repository:tag。标签是可选的,但是建议使用,因为这是 registry 用来给 Docker 镜像指定版本的机制。给仓库和标签起有意义的名字,例如 get-started:part2。这会把镜像放入 get-started 仓库,并且添加标签 part2。
运行 docker tag image 命令,用自己的 username,repository 和 标签名,这样镜像可以上传到指定的位置。命令的语法是:
docker tag image username/repository:tag
举个例子:
docker tag friendlyhello john/get-started:part2
运行 docker image ls 来查看新打标签的镜像:
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
friendlyhello latest d9e555c53008 minutes ago 195MB
john/get-started part2 d9e555c53008 minutes ago 195MB
python 2.7-slim 1c7128a655f6 days ago 183MB
...
发布镜像
将标记的镜像上载到repository:
docker push username/repository:tag
上传完成后,这次上传的镜像就可以公开访问了。如果你登录了 Docker Hub,就可以看见这个镜像和对应的 pull 命令。
从远程仓库获取并运行镜像
从现在起,你可以使用 docker run 命令在任何机器上运行你的应用程序:
docker run -p : username/repository:tag
如果镜像不在机器本地上,则 Docker 会从仓库获取镜像。
$ docker run -p : 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 在哪里运行,Docker 会获取你的镜像并运行(这里的镜像安装了 Python 和从 requirements.txt 文件指定的依赖,并会运行应用代码)。所有的东西都在一个包里,获取到就可以运行,不需要安装其他东西。
第二部分结论
本页就到此。在下一节中,我们将学习如何通过在service中运行此容器来扩展应用程序。
回顾和备忘单(可选)
下面是此页面中的基本 Docker 命令的列表,如果您想在继续之前先浏览一下,则提供一些相关命令。
docker build -t friendlyhello . # Create image using this directory's Dockerfile
docker run -p : friendlyhello # Run "friendlyhello" mapping port to
docker run -d -p : friendlyhello # 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 入门2 - 容器 【翻译】的更多相关文章
- docker入门——管理容器
除了交互式的容器(interactive container),我们也可以创建长期运行的容器.守护式容器(daemonized container)没有交互式会话,非常适合运行应用程序和服务.大多数时 ...
- Docker入门之三容器
上一篇博客学习了下镜像,今天来学习容器.容器类似一个手机中的沙盒环境,用来运行app实例.和镜像一样也是对容器的创建.删除.导出等. 由于我买的参考书中的例子好多都是基于linux的,所以我将dock ...
- docker入门(二)容器与镜像的理解
10张图带你深入理解Docker容器和镜像 申明:此篇文章是转载的(原文地址http://dockone.io/article/783),今天意外发现已经有人转载了(复制了),希望大家关注原创 原本打 ...
- docker入门(二)容器与镜像的关系
[编者的话]本文用图文并茂的方式介绍了容器.镜像的区别和Docker每个命令后面的技术细节,能够很好的帮助读者深入理解Docker. 这篇文章希望能够帮助读者深入理解Docker的命令,还有容器(co ...
- Docker 入门:容器
容器看着像机器,实际是进程,是一个运行时程序. 要操作一个 Docker 容器,只需要执行 docker container 命令. 可以通过 help 查看 run 运行容器 基础使用: docke ...
- Docker入门(三):容器(Containers)
这个<Docker入门系列>文档,是根据Docker官网(https://docs.docker.com)的帮助文档大致翻译而成.主要是作为个人学习记录.有错误的地方,Robin欢迎大家指 ...
- Docker入门(七):部署app
这个<Docker入门系列>文档,是根据Docker官网(https://docs.docker.com)的帮助文档大致翻译而成.主要是作为个人学习记录.有错误的地方,Robin欢迎大家指 ...
- Docker入门(六):Stacks
这个<Docker入门系列>文档,是根据Docker官网(https://docs.docker.com)的帮助文档大致翻译而成.主要是作为个人学习记录.有错误的地方,Robin欢迎大家指 ...
- Docker入门(五):Swarms
这个<Docker入门系列>文档,是根据Docker官网(https://docs.docker.com)的帮助文档大致翻译而成.主要是作为个人学习记录.有错误的地方,Robin欢迎大家指 ...
随机推荐
- linux查看服务安装目录redis
如果用命令 which redis 或者 whereis redis 都找不到安装目录, 可使用以下办法: ps -aux | grep redis 或者ps -ef|grep redis 假如得到 ...
- include指令与jsp:include动作标识的区别
include指令: 文件包含指令include是jsp的另一条指令标识.通过该指令可以在一个jsp页面中包含另一个jsp页面.不过该指令是静态包含,也就是说被包含文件中所有内容会被原样包含到jsp页 ...
- 微服务中使用MQ——RabbitMQ
概念 什么是消息 消息是指在两个独立的系统间传递的数据.这两个系统可以是两台计算机,也可以是两个进程. 消息是平台无关和语言无关的! 什么是队列 队列是一种数据结构,内部是用数组或链表实现的, 队列的 ...
- ORM 数据库使用
使用 Flask-SQLAlchemy 来操作数据库 1 配置 本文使用sqlite来作为例子演示,在config.py里面更新下数据库的配置 import os basedir = os.path ...
- 解决Maven的jar包冲突问题
1. 问题描述 控制台说:无法将 com.zpx.servlet.MyServlet 识别为 javax.servlet.Servlet 2. 问题原因 Maven的一个核心功能就是一键构建,所以Ma ...
- JAVA安全漫谈1-8笔记
一.反射篇1 classloader就是java的类加载器,告诉虚拟机如何加载这个类.默认情况下根据类名来加载类,类名必须是完整路径 public class class_init { { Syste ...
- ReactJS和AngularJS对比
Angular的特点: 优势: AngularJS是一套完整的框架,angular有自带的数据绑定.render渲染.angularUI库,过滤器,$filter,$directive(模板),$se ...
- 第04组 Beta冲刺(1)
队名:斗地组 组长博客:地址 作业博客:Beta冲刺(1/4) 各组员情况 林涛(组长) 过去两天完成了哪些任务: 1.分配展示任务 2.收集各个组员的进度 3.写博客 展示GitHub当日代码/文档 ...
- 淘宝rem适配方案
/*px 转化换 rem ,转化是 10 .比如:你的设计图为750,那么就 750 / 75 = 10 rem.设计图中你量尺寸都要除 75 就是 rem值.再比如量的设计图按钮宽度 66px,那么 ...
- 如何捕捉Desried Capabilities中的appPackafe和appActive
捕捉这两个参数需要借助adb工具的日志进行分析.ADB是一种命令行工具,用于PC和Android模拟器之前连接通信,集成在Android ADK中,默认在platfrom-tools目录下.在cmd运 ...