mirror of
https://github.com/dunwu/linux-tutorial.git
synced 2024-04-15 19:55:24 +08:00
104 lines
58 KiB
HTML
104 lines
58 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en-US">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||
<title>Docker 快速入门 | LINUX-TUTORIAL</title>
|
||
<meta name="generator" content="VuePress 1.8.2">
|
||
<link rel="icon" href="/linux-tutorial/favicon.ico">
|
||
<meta name="description" content="数据库教程">
|
||
|
||
<link rel="preload" href="/linux-tutorial/assets/css/0.styles.45d9d031.css" as="style"><link rel="preload" href="/linux-tutorial/assets/js/app.79a38eea.js" as="script"><link rel="preload" href="/linux-tutorial/assets/js/4.fb6e0f89.js" as="script"><link rel="preload" href="/linux-tutorial/assets/js/15.d217acb7.js" as="script"><link rel="preload" href="/linux-tutorial/assets/js/5.cb43ecfb.js" as="script"><link rel="prefetch" href="/linux-tutorial/assets/js/10.7933187b.js"><link rel="prefetch" href="/linux-tutorial/assets/js/11.b9b41530.js"><link rel="prefetch" href="/linux-tutorial/assets/js/12.70a5dba8.js"><link rel="prefetch" href="/linux-tutorial/assets/js/13.857dcc43.js"><link rel="prefetch" href="/linux-tutorial/assets/js/14.5a603a55.js"><link rel="prefetch" href="/linux-tutorial/assets/js/16.ad565eae.js"><link rel="prefetch" href="/linux-tutorial/assets/js/17.d43e9f56.js"><link rel="prefetch" href="/linux-tutorial/assets/js/18.aa00ff43.js"><link rel="prefetch" href="/linux-tutorial/assets/js/19.43ce44b3.js"><link rel="prefetch" href="/linux-tutorial/assets/js/20.5618e1ff.js"><link rel="prefetch" href="/linux-tutorial/assets/js/21.1c5a41d7.js"><link rel="prefetch" href="/linux-tutorial/assets/js/22.fbe9fdf1.js"><link rel="prefetch" href="/linux-tutorial/assets/js/23.a4fb0e74.js"><link rel="prefetch" href="/linux-tutorial/assets/js/24.e3a23b69.js"><link rel="prefetch" href="/linux-tutorial/assets/js/25.9896afe9.js"><link rel="prefetch" href="/linux-tutorial/assets/js/26.96164082.js"><link rel="prefetch" href="/linux-tutorial/assets/js/27.391033bb.js"><link rel="prefetch" href="/linux-tutorial/assets/js/28.703f74c2.js"><link rel="prefetch" href="/linux-tutorial/assets/js/29.02a952cb.js"><link rel="prefetch" href="/linux-tutorial/assets/js/30.7e13628f.js"><link rel="prefetch" href="/linux-tutorial/assets/js/31.c4652f75.js"><link rel="prefetch" href="/linux-tutorial/assets/js/32.05d2cbec.js"><link rel="prefetch" href="/linux-tutorial/assets/js/33.3b265df8.js"><link rel="prefetch" href="/linux-tutorial/assets/js/34.26330a03.js"><link rel="prefetch" href="/linux-tutorial/assets/js/35.417d706d.js"><link rel="prefetch" href="/linux-tutorial/assets/js/36.0ed775e0.js"><link rel="prefetch" href="/linux-tutorial/assets/js/37.34430c74.js"><link rel="prefetch" href="/linux-tutorial/assets/js/38.87d5e0ff.js"><link rel="prefetch" href="/linux-tutorial/assets/js/39.7b648b3e.js"><link rel="prefetch" href="/linux-tutorial/assets/js/40.3b7a219e.js"><link rel="prefetch" href="/linux-tutorial/assets/js/41.e727eee9.js"><link rel="prefetch" href="/linux-tutorial/assets/js/42.0134c187.js"><link rel="prefetch" href="/linux-tutorial/assets/js/43.175e982f.js"><link rel="prefetch" href="/linux-tutorial/assets/js/44.72d90888.js"><link rel="prefetch" href="/linux-tutorial/assets/js/45.d49955bd.js"><link rel="prefetch" href="/linux-tutorial/assets/js/46.a9c290ec.js"><link rel="prefetch" href="/linux-tutorial/assets/js/47.cc639f04.js"><link rel="prefetch" href="/linux-tutorial/assets/js/48.98c78321.js"><link rel="prefetch" href="/linux-tutorial/assets/js/49.a7c3afed.js"><link rel="prefetch" href="/linux-tutorial/assets/js/50.22d8c542.js"><link rel="prefetch" href="/linux-tutorial/assets/js/51.28055fcd.js"><link rel="prefetch" href="/linux-tutorial/assets/js/52.f8103df5.js"><link rel="prefetch" href="/linux-tutorial/assets/js/53.76541550.js"><link rel="prefetch" href="/linux-tutorial/assets/js/54.e78d2776.js"><link rel="prefetch" href="/linux-tutorial/assets/js/55.3ce3079c.js"><link rel="prefetch" href="/linux-tutorial/assets/js/56.832958c9.js"><link rel="prefetch" href="/linux-tutorial/assets/js/57.961ce896.js"><link rel="prefetch" href="/linux-tutorial/assets/js/58.6d6fbc82.js"><link rel="prefetch" href="/linux-tutorial/assets/js/59.d5e48112.js"><link rel="prefetch" href="/linux-tutorial/assets/js/6.c8f4721c.js"><link rel="prefetch" href="/linux-tutorial/assets/js/60.7927b23b.js"><link rel="prefetch" href="/linux-tutorial/assets/js/61.ee233f24.js"><link rel="prefetch" href="/linux-tutorial/assets/js/62.6ba50cc7.js"><link rel="prefetch" href="/linux-tutorial/assets/js/63.9cbf9f2b.js"><link rel="prefetch" href="/linux-tutorial/assets/js/64.0be148a4.js"><link rel="prefetch" href="/linux-tutorial/assets/js/65.c520257e.js"><link rel="prefetch" href="/linux-tutorial/assets/js/66.f2335390.js"><link rel="prefetch" href="/linux-tutorial/assets/js/67.e5737218.js"><link rel="prefetch" href="/linux-tutorial/assets/js/68.46427a01.js"><link rel="prefetch" href="/linux-tutorial/assets/js/69.450417bb.js"><link rel="prefetch" href="/linux-tutorial/assets/js/7.046e5a1b.js"><link rel="prefetch" href="/linux-tutorial/assets/js/70.072034d2.js"><link rel="prefetch" href="/linux-tutorial/assets/js/8.77fb8967.js"><link rel="prefetch" href="/linux-tutorial/assets/js/9.ebfa537e.js"><link rel="prefetch" href="/linux-tutorial/assets/js/vendors~flowchart.20a64d45.js"><link rel="prefetch" href="/linux-tutorial/assets/js/vendors~notification.ea176280.js">
|
||
<link rel="stylesheet" href="/linux-tutorial/assets/css/0.styles.45d9d031.css">
|
||
</head>
|
||
<body>
|
||
<div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/linux-tutorial/" class="home-link router-link-active"><img src="images/dunwu-logo-100.png" alt="LINUX-TUTORIAL" class="logo"> <span class="site-name can-hide">LINUX-TUTORIAL</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/linux-tutorial/linux/cli/" class="nav-link">
|
||
Linux 命令
|
||
</a></div><div class="nav-item"><a href="/linux-tutorial/linux/ops/" class="nav-link">
|
||
Linux 运维
|
||
</a></div><div class="nav-item"><a href="/linux-tutorial/linux/soft/" class="nav-link">
|
||
Linux 软件运维
|
||
</a></div><div class="nav-item"><a href="/linux-tutorial/docker/" class="nav-link router-link-active">
|
||
Docker 教程
|
||
</a></div><div class="nav-item"><a href="https://github.com/dunwu/blog" target="_blank" rel="noopener noreferrer" class="nav-link external">
|
||
🎯 博客
|
||
<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/dunwu/linux-tutorial" target="_blank" rel="noopener noreferrer" class="repo-link">
|
||
Github
|
||
<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/linux-tutorial/linux/cli/" class="nav-link">
|
||
Linux 命令
|
||
</a></div><div class="nav-item"><a href="/linux-tutorial/linux/ops/" class="nav-link">
|
||
Linux 运维
|
||
</a></div><div class="nav-item"><a href="/linux-tutorial/linux/soft/" class="nav-link">
|
||
Linux 软件运维
|
||
</a></div><div class="nav-item"><a href="/linux-tutorial/docker/" class="nav-link router-link-active">
|
||
Docker 教程
|
||
</a></div><div class="nav-item"><a href="https://github.com/dunwu/blog" target="_blank" rel="noopener noreferrer" class="nav-link external">
|
||
🎯 博客
|
||
<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/dunwu/linux-tutorial" target="_blank" rel="noopener noreferrer" class="repo-link">
|
||
Github
|
||
<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>Docker 快速入门</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/linux-tutorial/docker/docker-quickstart.html#一、docker-的简介" class="sidebar-link">一、Docker 的简介</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/linux-tutorial/docker/docker-quickstart.html#什么是-docker" class="sidebar-link">什么是 Docker</a></li><li class="sidebar-sub-header"><a href="/linux-tutorial/docker/docker-quickstart.html#为什么需要-docker" class="sidebar-link">为什么需要 Docker</a></li><li class="sidebar-sub-header"><a href="/linux-tutorial/docker/docker-quickstart.html#docker-的主要用途" class="sidebar-link">Docker 的主要用途</a></li><li class="sidebar-sub-header"><a href="/linux-tutorial/docker/docker-quickstart.html#docker-的核心概念" class="sidebar-link">Docker 的核心概念</a></li></ul></li><li><a href="/linux-tutorial/docker/docker-quickstart.html#二、docker-的运维" class="sidebar-link">二、Docker 的运维</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/linux-tutorial/docker/docker-quickstart.html#三、hello-world-实例" class="sidebar-link">三、Hello World 实例</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/linux-tutorial/docker/docker-quickstart.html#四、制作-docker-容器" class="sidebar-link">四、制作 Docker 容器</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/linux-tutorial/docker/docker-quickstart.html#编写-dockerfile-文件" class="sidebar-link">编写 Dockerfile 文件</a></li><li class="sidebar-sub-header"><a href="/linux-tutorial/docker/docker-quickstart.html#创建-image-文件" class="sidebar-link">创建 image 文件</a></li><li class="sidebar-sub-header"><a href="/linux-tutorial/docker/docker-quickstart.html#生成容器" class="sidebar-link">生成容器</a></li><li class="sidebar-sub-header"><a href="/linux-tutorial/docker/docker-quickstart.html#cmd-命令" class="sidebar-link">CMD 命令</a></li><li class="sidebar-sub-header"><a href="/linux-tutorial/docker/docker-quickstart.html#发布-image-文件" class="sidebar-link">发布 image 文件</a></li></ul></li><li><a href="/linux-tutorial/docker/docker-quickstart.html#参考资料" class="sidebar-link">参考资料</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="docker-快速入门"><a href="#docker-快速入门" class="header-anchor">#</a> Docker 快速入门</h1> <ul><li><a href="#%E4%B8%80docker-%E7%9A%84%E7%AE%80%E4%BB%8B">一、Docker 的简介</a></li> <li><a href="#%E4%BA%8Cdocker-%E7%9A%84%E8%BF%90%E7%BB%B4">二、Docker 的运维</a></li> <li><a href="#%E4%B8%89hello-world-%E5%AE%9E%E4%BE%8B">三、hello world 实例</a></li> <li><a href="#%E5%9B%9B%E5%88%B6%E4%BD%9C-docker-%E5%AE%B9%E5%99%A8">四、制作 Docker 容器</a></li> <li><a href="#%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99">参考资料</a></li></ul> <h2 id="一、docker-的简介"><a href="#一、docker-的简介" class="header-anchor">#</a> 一、Docker 的简介</h2> <h3 id="什么是-docker"><a href="#什么是-docker" class="header-anchor">#</a> 什么是 Docker</h3> <blockquote><p><strong>Docker 属于 Linux 容器的一种封装,提供简单易用的容器使用接口。</strong></p></blockquote> <p>它是目前最流行的 Linux 容器解决方案。</p> <p>Docker 将应用程序与该程序的依赖,打包在一个文件里面。运行这个文件,就会生成一个虚拟容器。程序在这个虚拟容器里运行,就好像在真实的物理机上运行一样。有了 Docker,就不用担心环境问题。</p> <p>总体来说,Docker 的接口相当简单,用户可以方便地创建和使用容器,把自己的应用放入容器。容器还可以进行版本管理、复制、分享、修改,就像管理普通的代码一样。</p> <h3 id="为什么需要-docker"><a href="#为什么需要-docker" class="header-anchor">#</a> 为什么需要 Docker</h3> <ul><li><strong>更高效的利用系统资源</strong> - 由于容器不需要进行硬件虚拟以及运行完整操作系统等额外开销,<code>Docker</code> 对系统资源的利用率更高。无论是应用执行速度、内存损耗或者文件存储速度,都要比传统虚拟机技术更高效。因此,相比虚拟机技术,一个相同配置的主机,往往可以运行更多数量的应用。</li> <li><strong>更快速的启动时间</strong> - 传统的虚拟机技术启动应用服务往往需要数分钟,而 <code>Docker</code> 容器应用,由于直接运行于宿主内核,无需启动完整的操作系统,因此可以做到秒级、甚至毫秒级的启动时间。大大的节约了开发、测试、部署的时间。</li> <li><strong>一致的运行环境</strong> - 开发过程中一个常见的问题是环境一致性问题。由于开发环境、测试环境、生产环境不一致,导致有些 bug 并未在开发过程中被发现。而 <code>Docker</code> 的镜像提供了除内核外完整的运行时环境,确保了应用运行环境一致性,从而不会再出现 <em>「这段代码在我机器上没问题啊」</em> 这类问题。</li> <li><strong>持续交付和部署</strong> - 对开发和运维(<a href="https://zh.wikipedia.org/wiki/DevOps" target="_blank" rel="noopener noreferrer">DevOps<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>)人员来说,最希望的就是一次创建或配置,可以在任意地方正常运行。使用 <code>Docker</code> 可以通过定制应用镜像来实现持续集成、持续交付、部署。开发人员可以通过 <a href="https://yeasy.gitbooks.io/docker_practice/image/dockerfile" target="_blank" rel="noopener noreferrer">Dockerfile<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a> 来进行镜像构建,并结合 <a href="https://en.wikipedia.org/wiki/Continuous_integration" target="_blank" rel="noopener noreferrer">持续集成(Continuous Integration)<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a> 系统进行集成测试,而运维人员则可以直接在生产环境中快速部署该镜像,甚至结合 <a href="https://en.wikipedia.org/wiki/Continuous_delivery" target="_blank" rel="noopener noreferrer">持续部署(Continuous Delivery/Deployment)<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a> 系统进行自动部署。而且使用 <a href="https://yeasy.gitbooks.io/docker_practice/image/build.html" target="_blank" rel="noopener noreferrer"><code>Dockerfile</code><span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a> 使镜像构建透明化,不仅仅开发团队可以理解应用运行环境,也方便运维团队理解应用运行所需条件,帮助更好的生产环境中部署该镜像。</li> <li><strong>更轻松的迁移</strong> - 由于 <code>Docker</code> 确保了执行环境的一致性,使得应用的迁移更加容易。<code>Docker</code> 可以在很多平台上运行,无论是物理机、虚拟机、公有云、私有云,甚至是笔记本,其运行结果是一致的。因此用户可以很轻易的将在一个平台上运行的应用,迁移到另一个平台上,而不用担心运行环境的变化导致应用无法正常运行的情况。</li> <li><strong>更轻松的维护和扩展</strong> - <code>Docker</code> 使用的分层存储以及镜像的技术,使得应用重复部分的复用更为容易,也使得应用的维护更新更加简单,基于基础镜像进一步扩展镜像也变得非常简单。此外,<code>Docker</code> 团队同各个开源项目团队一起维护了一大批高质量的 <a href="https://hub.docker.com/search/?type=image&image_filter=official" target="_blank" rel="noopener noreferrer">官方镜像<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>,既可以直接在生产环境使用,又可以作为基础进一步定制,大大的降低了应用服务的镜像制作成本。</li></ul> <p><img src="https://raw.githubusercontent.com/dunwu/images/dev/cs/os/docker/containers-and-vm.png" alt="img"></p> <h3 id="docker-的主要用途"><a href="#docker-的主要用途" class="header-anchor">#</a> Docker 的主要用途</h3> <p>Docker 提供了被称为容器的松散隔离环境,在环境中可以打包和运行应用程序。隔离和安全性允许您在给定主机上同时运行多个容器。容器是轻量级的,因为它们不需要管理程序的额外负载,而是直接在主机的内核中运行。这意味着您可以在给定的硬件组合上运行更多容器,而不是使用虚拟机。你甚至可以在实际上是虚拟机的主机中运行 Docker 容器!</p> <p>Docker 的主要用途,目前有三大类。</p> <ul><li>**提供一次性的环境。**比如,本地测试他人的软件、持续集成的时候提供单元测试和构建的环境。</li> <li>**提供弹性的云服务。**因为 Docker 容器可以随开随关,很适合动态扩容和缩容。</li> <li>**组建微服务架构。**通过多个容器,一台机器可以跑多个服务,因此在本机就可以模拟出微服务架构。</li></ul> <h3 id="docker-的核心概念"><a href="#docker-的核心概念" class="header-anchor">#</a> Docker 的核心概念</h3> <h4 id="镜像"><a href="#镜像" class="header-anchor">#</a> 镜像</h4> <p>Docker 把应用程序及其依赖,打包在镜像(Image)文件里面。</p> <p>我们都知道,操作系统分为内核和用户空间。对于 Linux 而言,内核启动后,会挂载 root 文件系统为其提供用户空间支持。而 Docker 镜像(Image),就相当于是一个 root 文件系统。比如官方镜像 ubuntu:18.04 就包含了完整的一套 Ubuntu 18.04 最小系统的 root 文件系统。</p> <p>Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。</p> <p><strong>分层存储</strong></p> <p>因为镜像包含操作系统完整的 root 文件系统,其体积往往是庞大的,因此在 Docker 设计时,就充分利用 Union FS 的技术,将其设计为分层存储的架构。所以严格来说,镜像并非是像一个 ISO 那样的打包文件,镜像只是一个虚拟的概念,其实际体现并非由一个文件组成,而是由一组文件系统组成,或者说,由多层文件系统联合组成。</p> <p>镜像构建时,会一层层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。比如,删除前一层文件的操作,实际不是真的删除前一层的文件,而是仅在当前层标记为该文件已删除。在最终容器运行的时候,虽然不会看到这个文件,但是实际上该文件会一直跟随镜像。因此,在构建镜像的时候,需要额外小心,每一层尽量只包含该层需要添加的东西,任何额外的东西应该在该层构建结束前清理掉。</p> <p>分层存储的特征还使得镜像的复用、定制变的更为容易。甚至可以用之前构建好的镜像作为基础层,然后进一步添加新的层,以定制自己所需的内容,构建新的镜像。</p> <h4 id="容器"><a href="#容器" class="header-anchor">#</a> 容器</h4> <p>镜像(<code>Image</code>)和容器(<code>Container</code>)的关系,就像是面向对象程序设计中的 <code>类</code> 和 <code>实例</code> 一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。</p> <p>容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的 <a href="https://en.wikipedia.org/wiki/Linux_namespaces" target="_blank" rel="noopener noreferrer">命名空间<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>。因此容器可以拥有自己的 <code>root</code> 文件系统、自己的网络配置、自己的进程空间,甚至自己的用户 ID 空间。容器内的进程是运行在一个隔离的环境里,使用起来,就好像是在一个独立于宿主的系统下操作一样。这种特性使得容器封装的应用比直接在宿主运行更加安全。也因为这种隔离的特性,很多人初学 Docker 时常常会混淆容器和虚拟机。</p> <p>前面讲过镜像使用的是分层存储,容器也是如此。每一个容器运行时,是以镜像为基础层,在其上创建一个当前容器的存储层,我们可以称这个为容器运行时读写而准备的存储层为<strong>容器存储层</strong>。</p> <p>容器存储层的生存周期和容器一样,容器消亡时,容器存储层也随之消亡。因此,任何保存于容器存储层的信息都会随容器删除而丢失。</p> <p>按照 Docker 最佳实践的要求,容器不应该向其存储层内写入任何数据,容器存储层要保持无状态化。所有的文件写入操作,都应该使用 <a href="https://yeasy.gitbooks.io/docker_practice/content/data_management/volume.html" target="_blank" rel="noopener noreferrer">数据卷(Volume)<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>、或者绑定宿主目录,在这些位置的读写会跳过容器存储层,直接对宿主(或网络存储)发生读写,其性能和稳定性更高。</p> <p>数据卷的生存周期独立于容器,容器消亡,数据卷不会消亡。因此,使用数据卷后,容器删除或者重新运行之后,数据却不会丢失。</p> <h4 id="仓库"><a href="#仓库" class="header-anchor">#</a> 仓库</h4> <p>镜像构建完成后,可以很容易的在当前宿主机上运行,但是,如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,<a href="https://yeasy.gitbooks.io/docker_practice/content/repository/registry.html" target="_blank" rel="noopener noreferrer">Docker Registry<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a> 就是这样的服务。</p> <p>一个 <strong>Docker Registry</strong> 中可以包含多个<strong>仓库</strong>(<code>Repository</code>);每个仓库可以包含多个<strong>标签</strong>(<code>Tag</code>);每个标签对应一个镜像。</p> <p>通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本。我们可以通过 <code><仓库名>:<标签></code> 的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 <code>latest</code> 作为默认标签。</p> <p>以 <a href="https://store.docker.com/images/ubuntu" target="_blank" rel="noopener noreferrer">Ubuntu 镜像<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a> 为例,<code>ubuntu</code> 是仓库的名字,其内包含有不同的版本标签,如,<code>16.04</code>, <code>18.04</code>。我们可以通过 <code>ubuntu:14.04</code>,或者 <code>ubuntu:18.04</code> 来具体指定所需哪个版本的镜像。如果忽略了标签,比如 <code>ubuntu</code>,那将视为 <code>ubuntu:latest</code>。</p> <p>仓库名经常以 <em>两段式路径</em> 形式出现,比如 <code>jwilder/nginx-proxy</code>,前者往往意味着 Docker Registry 多用户环境下的用户名,后者则往往是对应的软件名。但这并非绝对,取决于所使用的具体 Docker Registry 的软件或服务。</p> <h2 id="二、docker-的运维"><a href="#二、docker-的运维" class="header-anchor">#</a> 二、Docker 的运维</h2> <p>不同操作系统环境下安装 Docker 的方式有所不同,详情可以参:</p> <ul><li><a href="https://docs.docker.com/install/" target="_blank" rel="noopener noreferrer">Docker 官方安装指南<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li> <li><a href="https://docker_practice.gitee.io/install/" target="_blank" rel="noopener noreferrer">安装 Docker(中文)<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul> <p>国内访问 Docker 比较慢,如果需要提速,可以参考 <a href="https://docker_practice.gitee.io/install/mirror.html" target="_blank" rel="noopener noreferrer">镜像加速器<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></p> <p>安装完成后,运行下面的命令,验证是否安装成功。</p> <ul><li><code>docker version</code></li> <li><code>docker info</code></li></ul> <p>Docker 需要用户具有 sudo 权限,为了避免每次命令都输入<code>sudo</code>,可以把用户加入 Docker 用户组(<a href="https://docs.docker.com/install/linux/linux-postinstall/#manage-docker-as-a-non-root-user" target="_blank" rel="noopener noreferrer">官方文档<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>)。</p> <div class="language-bash extra-class"><pre class="language-bash"><code>$ <span class="token function">sudo</span> <span class="token function">usermod</span> -aG docker <span class="token environment constant">$USER</span>
|
||
</code></pre></div><p>Docker 是服务器----客户端架构。命令行运行<code>docker</code>命令的时候,需要本机有 Docker 服务。如果这项服务没有启动,可以用下面的命令启动(<a href="https://docs.docker.com/config/daemon/systemd/" target="_blank" rel="noopener noreferrer">官方文档<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>)。</p> <div class="language-bash extra-class"><pre class="language-bash"><code><span class="token comment"># service 命令的用法</span>
|
||
$ <span class="token function">sudo</span> <span class="token function">service</span> docker start
|
||
|
||
<span class="token comment"># systemctl 命令的用法</span>
|
||
$ <span class="token function">sudo</span> systemctl start docker
|
||
</code></pre></div><h2 id="三、hello-world-实例"><a href="#三、hello-world-实例" class="header-anchor">#</a> 三、Hello World 实例</h2> <p>下面,我们通过最简单的 image 文件"<a href="https://hub.docker.com/r/library/hello-world/" target="_blank" rel="noopener noreferrer">hello world"<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>,感受一下 Docker。</p> <p>需要说明的是,国内连接 Docker 的官方仓库很慢,还会断线,需要将默认仓库改成国内的镜像网站,具体的修改方法在<a href="http://www.ruanyifeng.com/blog/2018/02/docker-wordpress-tutorial.html" target="_blank" rel="noopener noreferrer">下一篇文章<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>的第一节。有需要的朋友,可以先看一下。</p> <p>首先,运行下面的命令,将 image 文件从仓库抓取到本地。</p> <blockquote><div class="language-bash extra-class"><pre class="language-bash"><code>$ docker image pull library/hello-world
|
||
</code></pre></div></blockquote> <p>上面代码中,<code>docker image pull</code>是抓取 image 文件的命令。<code>library/hello-world</code>是 image 文件在仓库里面的位置,其中<code>library</code>是 image 文件所在的组,<code>hello-world</code>是 image 文件的名字。</p> <p>由于 Docker 官方提供的 image 文件,都放在<a href="https://hub.docker.com/r/library/" target="_blank" rel="noopener noreferrer"><code>library</code><span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>组里面,所以它的是默认组,可以省略。因此,上面的命令可以写成下面这样。</p> <blockquote><div class="language-bash extra-class"><pre class="language-bash"><code>$ docker image pull hello-world
|
||
</code></pre></div></blockquote> <p>抓取成功以后,就可以在本机看到这个 image 文件了。</p> <blockquote><div class="language-bash extra-class"><pre class="language-bash"><code>$ docker image <span class="token function">ls</span>
|
||
</code></pre></div></blockquote> <p>现在,运行这个 image 文件。</p> <blockquote><div class="language-bash extra-class"><pre class="language-bash"><code>$ docker container run hello-world
|
||
</code></pre></div></blockquote> <p><code>docker container run</code>命令会从 image 文件,生成一个正在运行的容器实例。</p> <p>注意,<code>docker container run</code>命令具有自动抓取 image 文件的功能。如果发现本地没有指定的 image 文件,就会从仓库自动抓取。因此,前面的<code>docker image pull</code>命令并不是必需的步骤。</p> <p>如果运行成功,你会在屏幕上读到下面的输出。</p> <blockquote><div class="language-bash extra-class"><pre class="language-bash"><code>$ docker container run hello-world
|
||
|
||
Hello from Docker<span class="token operator">!</span>
|
||
This message shows that your installation appears to be working correctly.
|
||
|
||
<span class="token punctuation">..</span>. <span class="token punctuation">..</span>.
|
||
</code></pre></div></blockquote> <p>输出这段提示以后,<code>hello world</code>就会停止运行,容器自动终止。</p> <p>有些容器不会自动终止,因为提供的是服务。比如,安装运行 Ubuntu 的 image,就可以在命令行体验 Ubuntu 系统。</p> <blockquote><div class="language-bash extra-class"><pre class="language-bash"><code>$ docker container run -it ubuntu <span class="token function">bash</span>
|
||
</code></pre></div></blockquote> <p>对于那些不会自动终止的容器,必须使用<a href="https://docs.docker.com/engine/reference/commandline/container_kill/" target="_blank" rel="noopener noreferrer"><code>docker container kill</code><span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a> 命令手动终止。</p> <blockquote><div class="language-bash extra-class"><pre class="language-bash"><code>$ docker container <span class="token function">kill</span> <span class="token punctuation">[</span>containID<span class="token punctuation">]</span>
|
||
</code></pre></div></blockquote> <h2 id="四、制作-docker-容器"><a href="#四、制作-docker-容器" class="header-anchor">#</a> 四、制作 Docker 容器</h2> <p>下面我以 <a href="http://www.ruanyifeng.com/blog/2017/08/koa.html" target="_blank" rel="noopener noreferrer">koa-demos<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a> 项目为例,介绍怎么写 Dockerfile 文件,实现让用户在 Docker 容器里面运行 Koa 框架。</p> <p>作为准备工作,请先<a href="https://github.com/ruanyf/koa-demos/archive/master.zip" target="_blank" rel="noopener noreferrer">下载源码<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>。</p> <blockquote><div class="language-bash extra-class"><pre class="language-bash"><code>$ <span class="token function">git</span> clone https://github.com/ruanyf/koa-demos.git
|
||
$ <span class="token builtin class-name">cd</span> koa-demos
|
||
</code></pre></div></blockquote> <h3 id="编写-dockerfile-文件"><a href="#编写-dockerfile-文件" class="header-anchor">#</a> 编写 Dockerfile 文件</h3> <p>首先,在项目的根目录下,新建一个文本文件<code>.dockerignore</code>,写入下面的<a href="https://github.com/ruanyf/koa-demos/blob/master/.dockerignore" target="_blank" rel="noopener noreferrer">内容<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>。</p> <blockquote><div class="language-bash extra-class"><pre class="language-bash"><code>.git
|
||
node_modules
|
||
npm-debug.log
|
||
</code></pre></div></blockquote> <p>上面代码表示,这三个路径要排除,不要打包进入 image 文件。如果你没有路径要排除,这个文件可以不新建。</p> <p>然后,在项目的根目录下,新建一个文本文件 Dockerfile,写入下面的<a href="https://github.com/ruanyf/koa-demos/blob/master/Dockerfile" target="_blank" rel="noopener noreferrer">内容<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>。</p> <blockquote><div class="language-bash extra-class"><pre class="language-bash"><code>FROM node:8.4
|
||
COPY <span class="token builtin class-name">.</span> /app
|
||
WORKDIR /app
|
||
RUN <span class="token function">npm</span> <span class="token function">install</span> --registry<span class="token operator">=</span>https://registry.npm.taobao.org
|
||
EXPOSE <span class="token number">3000</span>
|
||
</code></pre></div></blockquote> <p>上面代码一共五行,含义如下。</p> <blockquote><ul><li><code>FROM node:8.4</code>:该 image 文件继承官方的 node image,冒号表示标签,这里标签是<code>8.4</code>,即 8.4 版本的 node。</li> <li><code>COPY . /app</code>:将当前目录下的所有文件(除了<code>.dockerignore</code>排除的路径),都拷贝进入 image 文件的<code>/app</code>目录。</li> <li><code>WORKDIR /app</code>:指定接下来的工作路径为<code>/app</code>。</li> <li><code>RUN npm install</code>:在<code>/app</code>目录下,运行<code>npm install</code>命令安装依赖。注意,安装后所有的依赖,都将打包进入 image 文件。</li> <li><code>EXPOSE 3000</code>:将容器 3000 端口暴露出来, 允许外部连接这个端口。</li></ul></blockquote> <h3 id="创建-image-文件"><a href="#创建-image-文件" class="header-anchor">#</a> 创建 image 文件</h3> <p>有了 Dockerfile 文件以后,就可以使用<code>docker image build</code>命令创建 image 文件了。</p> <blockquote><div class="language-bash extra-class"><pre class="language-bash"><code>$ docker image build -t koa-demo <span class="token builtin class-name">.</span>
|
||
<span class="token comment"># 或者</span>
|
||
$ docker image build -t koa-demo:0.0.1 <span class="token builtin class-name">.</span>
|
||
</code></pre></div></blockquote> <p>上面代码中,<code>-t</code>参数用来指定 image 文件的名字,后面还可以用冒号指定标签。如果不指定,默认的标签就是<code>latest</code>。最后的那个点表示 Dockerfile 文件所在的路径,上例是当前路径,所以是一个点。</p> <p>如果运行成功,就可以看到新生成的 image 文件<code>koa-demo</code>了。</p> <blockquote><div class="language-bash extra-class"><pre class="language-bash"><code>$ docker image <span class="token function">ls</span>
|
||
</code></pre></div></blockquote> <h3 id="生成容器"><a href="#生成容器" class="header-anchor">#</a> 生成容器</h3> <p><code>docker container run</code>命令会从 image 文件生成容器。</p> <blockquote><div class="language-bash extra-class"><pre class="language-bash"><code>$ docker container run -p <span class="token number">8000</span>:3000 -it koa-demo /bin/bash
|
||
<span class="token comment"># 或者</span>
|
||
$ docker container run -p <span class="token number">8000</span>:3000 -it koa-demo:0.0.1 /bin/bash
|
||
</code></pre></div></blockquote> <p>上面命令的各个参数含义如下:</p> <blockquote><ul><li><code>-p</code>参数:容器的 3000 端口映射到本机的 8000 端口。</li> <li><code>-it</code>参数:容器的 Shell 映射到当前的 Shell,然后你在本机窗口输入的命令,就会传入容器。</li> <li><code>koa-demo:0.0.1</code>:image 文件的名字(如果有标签,还需要提供标签,默认是 latest 标签)。</li> <li><code>/bin/bash</code>:容器启动以后,内部第一个执行的命令。这里是启动 Bash,保证用户可以使用 Shell。</li></ul></blockquote> <p>如果一切正常,运行上面的命令以后,就会返回一个命令行提示符。</p> <blockquote><div class="language-bash extra-class"><pre class="language-bash"><code>root@66d80f4aaf1e:/app<span class="token comment">#</span>
|
||
</code></pre></div></blockquote> <p>这表示你已经在容器里面了,返回的提示符就是容器内部的 Shell 提示符。执行下面的命令。</p> <blockquote><div class="language-bash extra-class"><pre class="language-bash"><code>root@66d80f4aaf1e:/app<span class="token comment"># node demos/01.js</span>
|
||
</code></pre></div></blockquote> <p>这时,Koa 框架已经运行起来了。打开本机的浏览器,访问 http://127.0.0.1:8000,网页显示"Not Found",这是因为这个 <a href="https://github.com/ruanyf/koa-demos/blob/master/demos/01.js" target="_blank" rel="noopener noreferrer">demo<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a> 没有写路由。</p> <p>这个例子中,Node 进程运行在 Docker 容器的虚拟环境里面,进程接触到的文件系统和网络接口都是虚拟的,与本机的文件系统和网络接口是隔离的,因此需要定义容器与物理机的端口映射(map)。</p> <p>现在,在容器的命令行,按下 Ctrl + c 停止 Node 进程,然后按下 Ctrl + d (或者输入 exit)退出容器。此外,也可以用<code>docker container kill</code>终止容器运行。</p> <blockquote><div class="language-bash extra-class"><pre class="language-bash"><code><span class="token comment"># 在本机的另一个终端窗口,查出容器的 ID</span>
|
||
$ docker container <span class="token function">ls</span>
|
||
|
||
<span class="token comment"># 停止指定的容器运行</span>
|
||
$ docker container <span class="token function">kill</span> <span class="token punctuation">[</span>containerID<span class="token punctuation">]</span>
|
||
</code></pre></div></blockquote> <p>容器停止运行之后,并不会消失,用下面的命令删除容器文件。</p> <blockquote><div class="language-bash extra-class"><pre class="language-bash"><code><span class="token comment"># 查出容器的 ID</span>
|
||
$ docker container <span class="token function">ls</span> --all
|
||
|
||
<span class="token comment"># 删除指定的容器文件</span>
|
||
$ docker container <span class="token function">rm</span> <span class="token punctuation">[</span>containerID<span class="token punctuation">]</span>
|
||
</code></pre></div></blockquote> <p>也可以使用<code>docker container run</code>命令的<code>--rm</code>参数,在容器终止运行后自动删除容器文件。</p> <blockquote><div class="language-bash extra-class"><pre class="language-bash"><code>$ docker container run --rm -p <span class="token number">8000</span>:3000 -it koa-demo /bin/bash
|
||
</code></pre></div></blockquote> <h3 id="cmd-命令"><a href="#cmd-命令" class="header-anchor">#</a> CMD 命令</h3> <p>上一节的例子里面,容器启动以后,需要手动输入命令<code>node demos/01.js</code>。我们可以把这个命令写在 Dockerfile 里面,这样容器启动以后,这个命令就已经执行了,不用再手动输入了。</p> <blockquote><div class="language-bash extra-class"><pre class="language-bash"><code>FROM node:8.4
|
||
COPY <span class="token builtin class-name">.</span> /app
|
||
WORKDIR /app
|
||
RUN <span class="token function">npm</span> <span class="token function">install</span> --registry<span class="token operator">=</span>https://registry.npm.taobao.org
|
||
EXPOSE <span class="token number">3000</span>
|
||
CMD node demos/01.js
|
||
</code></pre></div></blockquote> <p>上面的 Dockerfile 里面,多了最后一行<code>CMD node demos/01.js</code>,它表示容器启动后自动执行<code>node demos/01.js</code>。</p> <p>你可能会问,<code>RUN</code>命令与<code>CMD</code>命令的区别在哪里?简单说,<code>RUN</code>命令在 image 文件的构建阶段执行,执行结果都会打包进入 image 文件;<code>CMD</code>命令则是在容器启动后执行。另外,一个 Dockerfile 可以包含多个<code>RUN</code>命令,但是只能有一个<code>CMD</code>命令。</p> <p>注意,指定了<code>CMD</code>命令以后,<code>docker container run</code>命令就不能附加命令了(比如前面的<code>/bin/bash</code>),否则它会覆盖<code>CMD</code>命令。现在,启动容器可以使用下面的命令。</p> <blockquote><div class="language-bash extra-class"><pre class="language-bash"><code>$ docker container run --rm -p <span class="token number">8000</span>:3000 -it koa-demo:0.0.1
|
||
</code></pre></div></blockquote> <h3 id="发布-image-文件"><a href="#发布-image-文件" class="header-anchor">#</a> 发布 image 文件</h3> <p>容器运行成功后,就确认了 image 文件的有效性。这时,我们就可以考虑把 image 文件分享到网上,让其他人使用。</p> <p>首先,去 <a href="https://hub.docker.com/" target="_blank" rel="noopener noreferrer">hub.docker.com<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a> 或 <a href="https://cloud.docker.com/" target="_blank" rel="noopener noreferrer">cloud.docker.com<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a> 注册一个账户。然后,用下面的命令登录。</p> <blockquote><div class="language-bash extra-class"><pre class="language-bash"><code>$ docker login
|
||
</code></pre></div></blockquote> <p>接着,为本地的 image 标注用户名和版本。</p> <blockquote><div class="language-bash extra-class"><pre class="language-bash"><code>$ docker image tag <span class="token punctuation">[</span>imageName<span class="token punctuation">]</span> <span class="token punctuation">[</span>username<span class="token punctuation">]</span>/<span class="token punctuation">[</span>repository<span class="token punctuation">]</span>:<span class="token punctuation">[</span>tag<span class="token punctuation">]</span>
|
||
<span class="token comment"># 实例</span>
|
||
$ docker image tag koa-demos:0.0.1 ruanyf/koa-demos:0.0.1
|
||
</code></pre></div></blockquote> <p>也可以不标注用户名,重新构建一下 image 文件。</p> <blockquote><div class="language-bash extra-class"><pre class="language-bash"><code>$ docker image build -t <span class="token punctuation">[</span>username<span class="token punctuation">]</span>/<span class="token punctuation">[</span>repository<span class="token punctuation">]</span>:<span class="token punctuation">[</span>tag<span class="token punctuation">]</span> <span class="token builtin class-name">.</span>
|
||
</code></pre></div></blockquote> <p>最后,发布 image 文件。</p> <blockquote><div class="language-bash extra-class"><pre class="language-bash"><code>$ docker image push <span class="token punctuation">[</span>username<span class="token punctuation">]</span>/<span class="token punctuation">[</span>repository<span class="token punctuation">]</span>:<span class="token punctuation">[</span>tag<span class="token punctuation">]</span>
|
||
</code></pre></div></blockquote> <p>发布成功以后,登录 hub.docker.com,就可以看到已经发布的 image 文件。</p> <h2 id="参考资料"><a href="#参考资料" class="header-anchor">#</a> 参考资料</h2> <ul><li><a href="https://www.ruanyifeng.com/blog/2018/02/docker-tutorial.html" target="_blank" rel="noopener noreferrer">Docker 入门教程<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li> <li><a href="https://github.com/yeasy/docker_practice" target="_blank" rel="noopener noreferrer">Docker — 从入门到实践<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/dunwu/linux-tutorial/edit/master/docs/docker/docker-quickstart.md" target="_blank" rel="noopener noreferrer">帮助我们改善此页面!</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">上次更新:</span> <span class="time">19 minutes ago</span></div></footer> <!----> </main></div><div class="global-ui"><!----><!----></div></div>
|
||
<script src="/linux-tutorial/assets/js/app.79a38eea.js" defer></script><script src="/linux-tutorial/assets/js/4.fb6e0f89.js" defer></script><script src="/linux-tutorial/assets/js/15.d217acb7.js" defer></script><script src="/linux-tutorial/assets/js/5.cb43ecfb.js" defer></script>
|
||
</body>
|
||
</html>
|