作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.
Radek奥斯托夫斯基
验证专家 在工程

Radek是一名区块链工程师,对以太坊智能合约感兴趣. He also has extensive experience in machine learning.

以前在

Sony
Share

如果你喜欢鲸鱼, 或者只是对快速、无痛地将软件持续交付到生产环境感兴趣, 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

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地.

Transportation using shipping containers by land and by sea

这就是Docker发挥作用的地方它给 软件 行业.

How Is It Different from Virtual Machines?

乍一看,虚拟机和Docker容器似乎很相似. 然而,当你看一下下面的图表时,它们的主要区别就会变得明显:

Comparison chart of virtual machines (VMs) and containers

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 "你好莫比码头. 你好莫莉."

我们应该看到这样的输出:

你好莫比码头. 你好莫莉.

然而,幕后发生的事情比你想象的要多得多:

  • 镜像phusion/baseimage是从Docker Hub下载的(如果它还没有在本地缓存中)
  • A container based on this image was started
  • 命令 echo 是在容器内执行的
  • The container was stopped when the command exitted

在第一次运行时,您可能会注意到文本在屏幕上打印之前有延迟. 如果图像是在本地缓存的,那么所有操作只需要几分之一秒的时间. 有关最后一个容器的详细信息可以通过运行来检索 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 ();
        }
    }
}

Dockerfile

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 /乒乓球

Other Container and Image Operations

意料之中的是, 可以应用于容器和映像的操作列表相当长. For brevity, let us look at just a few of them:

  • stop -停止运行的容器.
  • start -启动已停止的容器.
  • commit - Creates a new image from a container’s changes.
  • rm -删除一个或多个容器.
  • rmi -删除一个或多个映像.
  • ps -列出容器.
  • images -列出图像.
  • exec - Runs a command in a 运行 container.

最后一个命令对于调试特别有用, 因为它可以让你连接到一个正在运行的容器的终端:

docker exec -i -t  bash

Docker Compose for the Microservice World

如果您不止有几个相互连接的容器,那么使用像 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

保证不会留下任何混乱或让事情处于不一致的状态.

Summary

Docker自己的座右铭中有一个很好的总结: 建造,运送,运行.

  • Build - Docker允许你用微服务构建你的应用程序, 无需担心开发环境和生产环境之间的不一致性, and without locking into any platform or language.
  • Ship - Docker可以让你设计应用程序开发的整个周期, 测试, 和分布, and manage it with a consistent user interface.
  • Run - Docker为您提供了在各种平台上安全可靠地部署可扩展服务的能力.

和鲸鱼一起游泳开心吗!

Part of this work is inspired by an excellent book 使用码头工人 作者:Adrian Mouat.

聘请Toptal这方面的专家.
现在雇佣
Radek奥斯托夫斯基

Radek奥斯托夫斯基

验证专家 在工程

普吉岛,泰国

2014年9月24日成为会员

作者简介

Radek是一名区块链工程师,对以太坊智能合约感兴趣. He also has extensive experience in machine learning.

作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.

以前在

Sony

World-class articles, delivered weekly.

By entering your email, you are agreeing to our 隐私政策.

World-class articles, delivered weekly.

By entering your email, you are agreeing to our 隐私政策.

Toptal开发者

加入总冠军® 社区.