作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.
Radek是一名区块链工程师,对以太坊智能合约感兴趣. He also has extensive experience in machine learning.
以前在
如果你喜欢鲸鱼, 或者只是对快速、无痛地将软件持续交付到生产环境感兴趣, then I invite you to read this introductory Docker Tutorial. 一切似乎都表明,软件容器是IT的未来, so let’s go for a quick dip with the container whales 莫比码头 and Molly.
Docker, represented by a logo with a friendly looking whale, 一个开放源码项目是否促进了软件容器内部应用程序的部署. 它的基本功能是通过Linux内核的资源隔离特性实现的, but it provides a user-friendly API on top of it. The first version was released in 2013, 从那以后,它变得非常受欢迎,并被许多大公司广泛使用,比如 eBay、Spotify、百度等等. 在上一轮融资中, Docker has landed a huge $95 million, and it’s on track to become a staple of DevOps服务.
Docker背后的哲学可以用下面一个简单的类比来说明. In the international transportation 行业, 货物必须通过不同的方式运输,比如叉车, 卡车, 火车, 起重机, 和船只. 这些货物有不同的形状和大小,有不同的储存要求:袋装糖, 牛奶罐, 植物等. 从历史上看, 这是一个痛苦的过程,依赖于人工干预,在每个中转点装卸.
It all changed with the uptake of intermodal containers. 因为它们有标准尺寸,制造时考虑到运输, 所有相关的机器都可以设计成以最少的人为干预来处理这些问题. 密封容器的额外好处是,它们可以保护内部环境,如敏感货物的温度和湿度. 结果是, 运输业可以不再担心货物本身,而把注意力集中在把货物从A地运到B地.
这就是Docker发挥作用的地方它给 软件 行业.
乍一看,虚拟机和Docker容器似乎很相似. 然而,当你看一下下面的图表时,它们的主要区别就会变得明显:
Applications 运行 in virtual machines, 除了管理程序, 需要操作系统的完整实例和任何支持库. 另一方面,容器与主机共享操作系统. Hypervisor可以与容器引擎(在映像上表示为Docker)相媲美,因为它管理容器的生命周期. 重要的区别在于,在容器内运行的进程就像主机上的本机进程一样, 并且不要引入与管理程序执行相关的任何开销. 此外,应用程序可以重用这些库并在容器之间共享数据.
As both technologies have different strengths, 将虚拟机和容器结合在一起的系统很常见. 一个完美的例子是在Docker安装部分中描述的名为Boot2Docker的工具.
At the top of the architecture diagram there are registries. 默认情况下,主注册表是Docker Hub,它托管公共和官方图像. 如果愿意,组织也可以托管自己的私有注册中心.
On the right-hand side we have images and containers. Images can be downloaded from registries explicitly (docker pull imageName
) or implicitly when starting a container. Once the image is downloaded it is cached locally.
容器是图像的实例——它们是有生命的东西. 可能有多个基于同一映像运行的容器.
在中心, there is the Docker daemon responsible for creating, 运行, 监控容器. It also takes care of building and storing images. Finally, on the left-hand side there is a Docker client. 它通过HTTP与守护进程通信. 在同一台机器上使用Unix套接字,但是可以通过基于HTTP的API进行远程管理.
For the latest 指令s you should always refer to the 官方文档.
Docker在Linux上本机运行,因此根据目标发行版,它可以像下面这样简单 安装docker.io
. Refer to the documentation for details. Normally in Linux, you prepend the Docker commands with sudo
, but we will skip it in this article for clarity.
As the Docker daemon uses Linux-specific kernel features, 不可能在Mac OS或窗户上运行Docker. 相反,你应该安装一个名为Boot2Docker的应用程序. The application consists of a VirtualBox Virtual Machine, 码头工人本身, and the Boot2Docker management utilities. You can follow the official installation 指令s for MacOS and 窗户 to install Docker on these platforms.
Let us begin this section with a quick example:
docker run phusion/baseimage echo "你好莫比码头. 你好莫莉."
我们应该看到这样的输出:
你好莫比码头. 你好莫莉.
然而,幕后发生的事情比你想象的要多得多:
在第一次运行时,您可能会注意到文本在屏幕上打印之前有延迟. 如果图像是在本地缓存的,那么所有操作只需要几分之一秒的时间. 有关最后一个容器的详细信息可以通过运行来检索 Docker ps - 1
:
容器ID IMAGE COMMAND 创建 状态 PORTS NAMES
af14bec37930 phusion / baseimage:最新 “你好,莫比鲸。 2分钟前 退出(0)3秒前 stoic_bardeen
正如你所看到的, 在Docker中运行一个简单的命令就像直接在标准终端上运行一样简单. To illustrate a more practical use case, throughout the remainder of this article, 我们将看到如何利用Docker来部署一个简单的web服务器应用程序. 为了让事情简单化, 我们将编写一个Java程序来处理对' /ping '的HTTP GET请求,并使用字符串' pong\n '进行响应。.
导入java.io.IOException;
导入java.io.OutputStream;
导入java.net.InetSocketAddress;
进口com.sun.net.http服务器.HttpExchange;
进口com.sun.net.http服务器.HttpHandler;
进口com.sun.net.http服务器.HttpServer;
乒乓{
public static void main(String[] args) throws Exception {
HttpServer 服务器 = HttpServer.create(new InetSocketAddress(8080), 0);
服务器.createContext("/ping", new MyHandler());
服务器.setExecutor(空);
服务器.开始();
}
static class MyHandler implements HttpHandler {
@Override
public void handle(HttpExchange t) throws IOException {
字符串响应= "pong\n";
t.sendResponseHeaders(200响应.长度());
输出流os = t.getResponseBody ();
os.写(响应.getBytes ());
os.close ();
}
}
}
Before jumping in and building your own Docker image, 首先检查Docker Hub或您可以访问的任何私有注册表中是否有现有的注册表,这是一个很好的做法. 例如,我们不需要自己安装Java,而是使用官方图片: java: 8
.
要构建映像,首先我们需要决定要使用的基本映像. 表示为 FROM 指令. 这是官方图片 Java 8 来自码头中心. We are going to copy it into our Java file by issuing a COPY 指令. Next, we are going to compile it with RUN. 暴露 指令表示映像将在特定端口上提供服务. 入口点 当基于此映像的容器启动时,我们想要执行的指令是什么 CMD indicates the default parameters we are going to pass to it.
从java: 8
复制乒乓球.java /
跑javac乒乓球.java
8080年公开
入口点(“java”)
CMD(“乒乓球”)
将这些指令保存在一个名为“Dockerfile”的文件中之后, we can build the corresponding Docker image by executing:
Docker build -t total /乒乓 .
The 官方文档 for Docker has a 专门讨论最佳实践的部分 关于写Dockerfile.
当图像已经建立,我们可以把它作为一个容器的生活. 有几种方法可以运行容器,但让我们从一个简单的开始:
docker run -d -p 8080:8080 toptal /乒乓球
where -p [port-on-the-host]:[port-in-the-container] 表示主机和容器上的端口映射. 此外, 我们告诉Docker在后台将容器作为守护进程运行 -d. 您可以通过尝试访问“http://localhost:8080/ping”来测试web服务器应用程序是否正在运行。. Note that on platforms where Boot2docker is being used, 你需要将' localhost '替换为运行Docker的虚拟机的IP地址.
在Linux上:
curl http://localhost: 8080 /平
在需要Boot2Docker的平台上:
Curl $(boot2docker ip):8080/ping
If all goes well, you should see the response:
pong
万岁,我们的第一个定制Docker容器活跃起来了! We could also start the container in an interactive mode -i -t. 在本例中,我们将重写 入口点 command so we are presented with a bash terminal. 现在我们可以执行任何我们想要的命令,但是退出容器会阻止它:
docker run -i -t --入口点="bash" toptal /乒乓球
还有更多的选项可用于启动容器. 让我们再讲几个. 例如, if we want to persist data outside of the container, 我们可以使用命令与容器共享主机文件系统 -v. 缺省情况下,访问模式为读写模式,但可以通过追加修改为只读模式 :ro
到容器内的卷路径. 当我们需要在容器内使用任何安全信息(如凭据和私钥)时,卷尤为重要, which shouldn’t be stored on the image. 另外, it could also prevent the duplication of data, 例如,通过将本地Maven存储库映射到容器来避免两次下载Internet.
Docker还具有将容器连接在一起的能力. 即使没有任何端口公开,链接的容器也可以相互通信. 它可以通过 链接other-container-name. Below is an example combining mentioned above parameters:
Docker运行-p 9999:8080
--link otherContainerA --link otherContainerB
- v /用户/用户/美元.m2 /存储库:/ home / user /.m2 /库
toptal /乒乓球
意料之中的是, 可以应用于容器和映像的操作列表相当长. For brevity, let us look at just a few of them:
最后一个命令对于调试特别有用, 因为它可以让你连接到一个正在运行的容器的终端:
docker exec -i -t bash
如果您不止有几个相互连接的容器,那么使用像 docker-compose. 在配置文件中, 您描述了如何启动容器以及它们应该如何相互链接. 不管所涉及的容器的数量及其依赖关系如何, you could have all of them up and 运行 with one command: docker-compose起来
.
让我们着眼于项目生命周期的三个阶段,并看看我们友好的鲸鱼玩家是如何提供帮助的.
Docker帮助您保持本地开发环境的整洁. 而不是安装不同服务(如Java)的多个版本, Kafka, Spark, 卡珊德拉, etc.,您可以在必要时启动和停止所需的容器. 您可以更进一步,并排运行多个软件堆栈,以避免依赖版本的混淆.
With Docker, you can save time, effort, and money. If your project is very complex to set up, “dockerise” it. Go through the pain of creating a Docker image once, 从这一点开始,每个人都可以快速启动一个容器.
您还可以在本地(或CI上)运行一个“集成环境”,并将存根替换为运行在Docker容器中的实际服务.
With Dockerfile, it is easy to achieve reproducible builds. Jenkins或其他CI解决方案可以配置为为每次构建创建一个Docker映像. 您可以将部分或全部映像存储在私有Docker注册表中,以备将来参考.
使用Docker,您只需测试需要测试的内容,并将环境排除在外. 在运行的容器上执行测试可以帮助保持事情的可预测性.
使用软件容器的另一个有趣的特性是,可以很容易地使用相同的开发设置派生出从属机器. 它对于集群部署的负载测试特别有用.
Docker可以作为开发人员和操作人员之间的公共接口,消除摩擦的来源. 它还鼓励在管道的每一步使用相同的映像/二进制文件. 此外, 能够部署完全经过测试的容器而不存在环境差异,有助于确保在构建过程中不会引入错误.
You can seamlessly migrate applications into production. 曾经是一个繁琐而不稳定的过程,现在可以变得如此简单:
docker stop container-id; docker run new-image
And if something goes wrong when deploying a new version, 您总是可以快速回滚或更改到其他容器:
docker stop container-id; docker start other-container-id
保证不会留下任何混乱或让事情处于不一致的状态.
Docker自己的座右铭中有一个很好的总结: 建造,运送,运行.
和鲸鱼一起游泳开心吗!
Part of this work is inspired by an excellent book 使用码头工人 作者:Adrian Mouat.
普吉岛,泰国
2014年9月24日成为会员
World-class articles, delivered weekly.
World-class articles, delivered weekly.