learn.lianglianglee.com/专栏/由浅入深吃透 Docker-完/01 Docker 安装:入门案例带你了解容器技术原理.md.html
2022-05-11 18:57:05 +08:00

905 lines
25 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<!-- saved from url=(0046)https://kaiiiz.github.io/hexo-theme-book-demo/ -->
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no">
<link rel="icon" href="/static/favicon.png">
<title>01 Docker 安装:入门案例带你了解容器技术原理.md.html</title>
<!-- Spectre.css framework -->
<link rel="stylesheet" href="/static/index.css">
<!-- theme css & js -->
<meta name="generator" content="Hexo 4.2.0">
</head>
<body>
<div class="book-container">
<div class="book-sidebar">
<div class="book-brand">
<a href="/">
<img src="/static/favicon.png">
<span>技术文章摘抄</span>
</a>
</div>
<div class="book-menu uncollapsible">
<ul class="uncollapsible">
<li><a href="/" class="current-tab">首页</a></li>
</ul>
<ul class="uncollapsible">
<li><a href="../">上一级</a></li>
</ul>
<ul class="uncollapsible">
<li>
<a href="/专栏/由浅入深吃透 Docker-完/00 溯本求源,吃透 Docker.md.html">00 溯本求源,吃透 Docker.md.html</a>
</li>
<li>
<a class="current-tab" href="/专栏/由浅入深吃透 Docker-完/01 Docker 安装:入门案例带你了解容器技术原理.md.html">01 Docker 安装:入门案例带你了解容器技术原理.md.html</a>
</li>
<li>
<a href="/专栏/由浅入深吃透 Docker-完/02 核心概念:镜像、容器、仓库,彻底掌握 Docker 架构核心设计理念.md.html">02 核心概念:镜像、容器、仓库,彻底掌握 Docker 架构核心设计理念.md.html</a>
</li>
<li>
<a href="/专栏/由浅入深吃透 Docker-完/03 镜像使用Docker 环境下如何配置你的镜像?.md.html">03 镜像使用Docker 环境下如何配置你的镜像?.md.html</a>
</li>
<li>
<a href="/专栏/由浅入深吃透 Docker-完/04 容器操作:得心应手掌握 Docker 容器基本操作.md.html">04 容器操作:得心应手掌握 Docker 容器基本操作.md.html</a>
</li>
<li>
<a href="/专栏/由浅入深吃透 Docker-完/05 仓库访问:怎样搭建属于你的私有仓库?.md.html">05 仓库访问:怎样搭建属于你的私有仓库?.md.html</a>
</li>
<li>
<a href="/专栏/由浅入深吃透 Docker-完/06 最佳实践:如何在生产中编写最优 Dockerfile.md.html">06 最佳实践:如何在生产中编写最优 Dockerfile.md.html</a>
</li>
<li>
<a href="/专栏/由浅入深吃透 Docker-完/07 Docker 安全:基于内核的弱隔离系统如何保障安全性?.md.html">07 Docker 安全:基于内核的弱隔离系统如何保障安全性?.md.html</a>
</li>
<li>
<a href="/专栏/由浅入深吃透 Docker-完/08 容器监控:容器监控原理及 cAdvisor 的安装与使用.md.html">08 容器监控:容器监控原理及 cAdvisor 的安装与使用.md.html</a>
</li>
<li>
<a href="/专栏/由浅入深吃透 Docker-完/09 资源隔离:为什么构建容器需要 Namespace .md.html">09 资源隔离:为什么构建容器需要 Namespace .md.html</a>
</li>
<li>
<a href="/专栏/由浅入深吃透 Docker-完/10 资源限制:如何通过 Cgroups 机制实现资源限制?.md.html">10 资源限制:如何通过 Cgroups 机制实现资源限制?.md.html</a>
</li>
<li>
<a href="/专栏/由浅入深吃透 Docker-完/11 组件组成:剖析 Docker 组件作用及其底层工作原理.md.html">11 组件组成:剖析 Docker 组件作用及其底层工作原理.md.html</a>
</li>
<li>
<a href="/专栏/由浅入深吃透 Docker-完/12 网络模型:剖析 Docker 网络实现及 Libnetwork 底层原理.md.html">12 网络模型:剖析 Docker 网络实现及 Libnetwork 底层原理.md.html</a>
</li>
<li>
<a href="/专栏/由浅入深吃透 Docker-完/13 数据存储:剖析 Docker 卷与持久化数据存储的底层原理.md.html">13 数据存储:剖析 Docker 卷与持久化数据存储的底层原理.md.html</a>
</li>
<li>
<a href="/专栏/由浅入深吃透 Docker-完/14 文件存储驱动AUFS 文件系统原理及生产环境的最佳配置.md.html">14 文件存储驱动AUFS 文件系统原理及生产环境的最佳配置.md.html</a>
</li>
<li>
<a href="/专栏/由浅入深吃透 Docker-完/15 文件存储驱动Devicemapper 文件系统原理及生产环境的最佳配置.md.html">15 文件存储驱动Devicemapper 文件系统原理及生产环境的最佳配置.md.html</a>
</li>
<li>
<a href="/专栏/由浅入深吃透 Docker-完/16 文件存储驱动OverlayFS 文件系统原理及生产环境的最佳配置.md.html">16 文件存储驱动OverlayFS 文件系统原理及生产环境的最佳配置.md.html</a>
</li>
<li>
<a href="/专栏/由浅入深吃透 Docker-完/17 原理实践:自己动手使用 Golang 开发 Docker.md.html">17 原理实践:自己动手使用 Golang 开发 Docker.md.html</a>
</li>
<li>
<a href="/专栏/由浅入深吃透 Docker-完/18 原理实践:自己动手使用 Golang 开发 Docker.md.html">18 原理实践:自己动手使用 Golang 开发 Docker.md.html</a>
</li>
<li>
<a href="/专栏/由浅入深吃透 Docker-完/19 如何使用 Docker Compose 解决开发环境的依赖?.md.html">19 如何使用 Docker Compose 解决开发环境的依赖?.md.html</a>
</li>
<li>
<a href="/专栏/由浅入深吃透 Docker-完/20 如何在生产环境中使用 Docker Swarm 调度容器?.md.html">20 如何在生产环境中使用 Docker Swarm 调度容器?.md.html</a>
</li>
<li>
<a href="/专栏/由浅入深吃透 Docker-完/21 如何使 Docker 和 Kubernetes 结合发挥容器的最大价值?.md.html">21 如何使 Docker 和 Kubernetes 结合发挥容器的最大价值?.md.html</a>
</li>
<li>
<a href="/专栏/由浅入深吃透 Docker-完/22 多阶级构建Docker 下如何实现镜像多阶级构建?.md.html">22 多阶级构建Docker 下如何实现镜像多阶级构建?.md.html</a>
</li>
<li>
<a href="/专栏/由浅入深吃透 Docker-完/23 DevOps容器化后如何通过 DevOps 提高协作效能?.md.html">23 DevOps容器化后如何通过 DevOps 提高协作效能?.md.html</a>
</li>
<li>
<a href="/专栏/由浅入深吃透 Docker-完/24 CICD容器化后如何实现持续集成与交付.md.html">24 CICD容器化后如何实现持续集成与交付.md.html</a>
</li>
<li>
<a href="/专栏/由浅入深吃透 Docker-完/25 CICD容器化后如何实现持续集成与交付.md.html">25 CICD容器化后如何实现持续集成与交付.md.html</a>
</li>
<li>
<a href="/专栏/由浅入深吃透 Docker-完/26 结束语 展望未来Docker 的称霸之路.md.html">26 结束语 展望未来Docker 的称霸之路.md.html</a>
</li>
</ul>
</div>
</div>
<div class="sidebar-toggle" onclick="sidebar_toggle()" onmouseover="add_inner()" onmouseleave="remove_inner()">
<div class="sidebar-toggle-inner"></div>
</div>
<script>
function add_inner() {
let inner = document.querySelector('.sidebar-toggle-inner')
inner.classList.add('show')
}
function remove_inner() {
let inner = document.querySelector('.sidebar-toggle-inner')
inner.classList.remove('show')
}
function sidebar_toggle() {
let sidebar_toggle = document.querySelector('.sidebar-toggle')
let sidebar = document.querySelector('.book-sidebar')
let content = document.querySelector('.off-canvas-content')
if (sidebar_toggle.classList.contains('extend')) { // show
sidebar_toggle.classList.remove('extend')
sidebar.classList.remove('hide')
content.classList.remove('extend')
} else { // hide
sidebar_toggle.classList.add('extend')
sidebar.classList.add('hide')
content.classList.add('extend')
}
}
function open_sidebar() {
let sidebar = document.querySelector('.book-sidebar')
let overlay = document.querySelector('.off-canvas-overlay')
sidebar.classList.add('show')
overlay.classList.add('show')
}
function hide_canvas() {
let sidebar = document.querySelector('.book-sidebar')
let overlay = document.querySelector('.off-canvas-overlay')
sidebar.classList.remove('show')
overlay.classList.remove('show')
}
</script>
<div class="off-canvas-content">
<div class="columns">
<div class="column col-12 col-lg-12">
<div class="book-navbar">
<!-- For Responsive Layout -->
<header class="navbar">
<section class="navbar-section">
<a onclick="open_sidebar()">
<i class="icon icon-menu"></i>
</a>
</section>
</header>
</div>
<div class="book-content" style="max-width: 960px; margin: 0 auto;
overflow-x: auto;
overflow-y: hidden;">
<div class="book-post">
<p id="tip" align="center"></p>
<div><h1>01 Docker 安装:入门案例带你了解容器技术原理</h1>
<p>咱们第一课时就先聊聊 Docker 的基础内容Docker 能做什么,怎么安装 Docker以及容器技术的原理。</p>
<h3>Docker 能做什么?</h3>
<p>众所周知Docker 是一个用于开发发布和运行应用程序的开放平台。通俗地讲Docker 类似于集装箱。在一艘大船上各种货物要想被整齐摆放并且相互不受到影响我们就需要把各种货物进行集装箱标准化。有了集装箱我们就不需要专门运输水果或者化学用品的船了。我们可以把各种货品通过集装箱打包然后统一放到一艘船上运输。Docker 要做的就是把各种软件打包成一个集装箱(镜像),然后分发,且在运行的时候可以相互隔离。</p>
<p>到此,相信你已经迫不及待想要体验下了,下面就让我们来安装一个 Docker。</p>
<h3>CentOS 下安装 Docker</h3>
<p>Docker 是跨平台的解决方案,它支持在当前主流的各大平台安装,包括 Ubuntu、RHEL、CentOS、Debian 等 Linux 发行版,同时也可以在 OSX 、Microsoft Windows 等非 Linux 平台下安装使用。</p>
<p>因为 Linux 是 Docker 的原生支持平台,所以推荐你在 Linux 上使用 Docker。由于生产环境中我们使用 CentOS 较多,下面主要针对在 CentOS 平台下安装和使用 Docker 展开介绍。</p>
<h4>操作系统要求</h4>
<p>要安装 Docker我们需要 CentOS 7 及以上的发行版本。建议使用<code>overlay2</code>存储驱动程序。</p>
<h4>卸载已有 Docker</h4>
<p>如果你已经安装过旧版的 Docker可以先执行以下命令卸载旧版 Docker。</p>
<pre><code>$ sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
</code></pre>
<h4>安装 Docker</h4>
<p>首次安装 Docker 之前,需要添加 Docker 安装源。添加之后,我们就可以从已经配置好的源,安装和更新 Docker。添加 Docker 安装源的命令如下:</p>
<pre><code>$ sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
</code></pre>
<p>正常情况下,直接安装最新版本的 Docker 即可,因为最新版本的 Docker 有着更好的稳定性和安全性。你可以使用以下命令安装最新版本的 Docker。</p>
<pre><code>$ sudo yum install docker-ce docker-ce-cli containerd.io
</code></pre>
<p>如果你想要安装指定版本的 Docker可以使用以下命令</p>
<pre><code>$ sudo yum list docker-ce --showduplicates | sort -r
docker-ce.x86_64 18.06.1.ce-3.el7 docker-ce-stable
docker-ce.x86_64 18.06.0.ce-3.el7 docker-ce-stable
docker-ce.x86_64 18.03.1.ce-1.el7.centos docker-ce-stable
docker-ce.x86_64 18.03.0.ce-1.el7.centos docker-ce-stable
docker-ce.x86_64 17.12.1.ce-1.el7.centos docker-ce-stable
docker-ce.x86_64 17.12.0.ce-1.el7.centos docker-ce-stable
docker-ce.x86_64 17.09.1.ce-1.el7.centos docker-ce-stable
</code></pre>
<p>然后选取想要的版本执行以下命令:</p>
<pre><code>$ sudo yum install docker-ce-&lt;VERSION_STRING&gt; docker-ce-cli-&lt;VERSION_STRING&gt; containerd.io
</code></pre>
<p>安装完成后,使用以下命令启动 Docker。</p>
<pre><code>$ sudo systemctl start docker
</code></pre>
<p>这里有一个国际惯例,安装完成后,我们需要使用以下命令启动一个 hello world 的容器。</p>
<pre><code>$ sudo docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
0e03bdcc26d7: Pull complete
Digest: sha256:7f0a9f93b4aa3022c3a4c147a449bf11e0941a1fd0bf4a8e6c9408b2600777c5
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
</code></pre>
<p>运行上述命令Docker 首先会检查本地是否有<code>hello-world</code>这个镜像如果发现本地没有这个镜像Docker 就会去 Docker Hub 官方仓库下载此镜像,然后运行它。最后我们看到该镜像输出 &quot;Hello from Docker!&quot; 并退出。</p>
<blockquote>
<p>安装完成后默认 docker 命令只能以 root 用户执行,如果想允许普通用户执行 docker 命令,需要执行以下命令 sudo groupadd docker &amp;&amp; sudo gpasswd -a ${USER} docker &amp;&amp; sudo systemctl restart docker ,执行完命令后,退出当前命令行窗口并打开新的窗口即可。</p>
</blockquote>
<p>安装完 Docker先不着急使用先来了解下容器的技术原理这样才能知其所以然。</p>
<h3>容器技术原理</h3>
<p>提起容器就不得不说 chroot因为 chroot 是最早的容器雏形。chroot 意味着切换根目录,有了 chroot 就意味着我们可以把任何目录更改为当前进程的根目录,这与容器非常相似,下面我们通过一个实例了解下 chroot。</p>
<h4>chroot</h4>
<p>什么是 chroot 呢?下面是 chroot 维基百科定义:</p>
<blockquote>
<p>chroot 是在 Unix 和 Linux 系统的一个操作,针对正在运作的软件行程和它的子进程,改变它外显的根目录。一个运行在这个环境下,经由 chroot 设置根目录的程序,它不能够对这个指定根目录之外的文件进行访问动作,不能读取,也不能更改它的内容。</p>
</blockquote>
<p>通俗地说 chroot 就是可以改变某进程的根目录,使这个程序不能访问目录之外的其他目录,这个跟我们在一个容器中是很相似的。下面我们通过一个实例来演示下 chroot。</p>
<p>首先我们在当前目录下创建一个 rootfs 目录:</p>
<pre><code>$ mkdir rootfs
</code></pre>
<p>这里为了方便演示,我使用现成的 busybox 镜像来创建一个系统,镜像的概念和组成后面我会详细讲解,如果你没有 Docker 基础可以把下面的操作命令理解成在 rootfs 下创建了一些目录和放置了一些二进制文件。</p>
<pre><code>$ cd rootfs
$ docker export $(docker create busybox) -o busybox.tar
$ tar -xf busybox.tar
</code></pre>
<p>执行完上面的命令后,在 rootfs 目录下,我们会得到一些目录和文件。下面我们使用 ls 命令查看一下 rootfs 目录下的内容。</p>
<pre><code>$ ls
bin busybox.tar dev etc home proc root sys tmp usr var
</code></pre>
<p>可以看到我们在 rootfs 目录下初始化了一些目录,下面让我们通过一条命令来见证 chroot 的神奇之处。使用以下命令,可以启动一个 sh 进程,并且把 /home/centos/rootfs 作为 sh 进程的根目录。</p>
<pre><code>$ chroot /home/centos/rootfs /bin/sh
</code></pre>
<p>此时,我们的命令行窗口已经处于上述命令启动的 sh 进程中。在当前 sh 命令行窗口下,我们使用 ls 命令查看一下当前进程,看是否真的与主机上的其他目录隔离开了。</p>
<pre><code>/ # /bin/ls /
bin busybox.tar dev etc home proc root sys tmp usr var
</code></pre>
<p>这里可以看到当前进程的根目录已经变成了主机上的 /home/centos/rootfs 目录。这样就实现了当前进程与主机的隔离。到此为止,一个目录隔离的容器就完成了。
但是,此时还不能称之为一个容器,为什么呢?你可以在上一步(使用 chroot 启动命令行窗口)执行以下命令,查看如下路由信息:</p>
<pre><code>/etc # /bin/ip route
default via 172.20.1.1 dev eth0
172.17.0.0/16 dev docker0 scope link src 172.17.0.1
172.20.1.0/24 dev eth0 scope link src 172.20.1.3
</code></pre>
<p>执行 ip route 命令后,你可以看到网络信息并没有隔离,实际上进程等信息此时也并未隔离。要想实现一个完整的容器,我们还需要 Linux 的其他三项技术: Namespace、Cgroups 和联合文件系统。</p>
<p>Docker 是利用 Linux 的 Namespace 、Cgroups 和联合文件系统三大机制来保证实现的, 所以它的原理是使用 Namespace 做主机名、网络、PID 等资源的隔离,使用 Cgroups 对进程或者进程组做资源例如CPU、内存等的限制联合文件系统用于镜像构建和容器运行环境。</p>
<p>后面我会对这些技术进行详细讲解,这里我就简单解释下它们的作用。</p>
<h4>Namespace</h4>
<p>Namespace 是 Linux 内核的一项功能该功能对内核资源进行隔离使得容器中的进程都可以在单独的命名空间中运行并且只可以访问当前容器命名空间的资源。Namespace 可以隔离进程 ID、主机名、用户 ID、文件名、网络访问和进程间通信等相关资源。</p>
<p>Docker 主要用到以下五种命名空间。</p>
<ul>
<li>pid namespace用于隔离进程 ID。</li>
<li>net namespace隔离网络接口在虚拟的 net namespace 内用户可以拥有自己独立的 IP、路由、端口等。</li>
<li>mnt namespace文件系统挂载点隔离。</li>
<li>ipc namespace信号量,消息队列和共享内存的隔离。</li>
<li>uts namespace主机名和域名的隔离。</li>
</ul>
<h4>Cgroups</h4>
<p>Cgroups 是一种 Linux 内核功能可以限制和隔离进程的资源使用情况CPU、内存、磁盘 I/O、网络等。在容器的实现中Cgroups 通常用来限制容器的 CPU 和内存等资源的使用。</p>
<h4>联合文件系统</h4>
<p>联合文件系统,又叫 UnionFS是一种通过创建文件层进程操作的文件系统因此联合文件系统非常轻快。Docker 使用联合文件系统为容器提供构建层,使得容器可以实现写时复制以及镜像的分层构建和存储。常用的联合文件系统有 AUFS、Overlay 和 Devicemapper 等。</p>
<h3>结语</h3>
<p>容器技术从 1979 年 chroot 的首次问世便已崭露头角,但是到了 2013 年Dokcer 的横空出世才使得容器技术迅速发展,可见 Docker 对于容器技术的推动力和影响力。</p>
<blockquote>
<p>另外, Docker 还提供了工具和平台来管理容器的生命周期:</p>
<ol>
<li>使用容器开发应用程序及其支持组件。</li>
<li>容器成为分发和测试你的应用程序的单元。</li>
<li>可以将应用程序作为容器或协调服务部署到生产环境中。无论您的生产环境是本地数据中心,云提供商还是两者的混合,其工作原理都相同。</li>
</ol>
</blockquote>
<p>到此,相信你已经了解了实现容器的基本技术原理,并且对 Docker 的作用有了一定认知。那么你知道为什么容器技术在 Docker 出现之前一直没有爆发的根本原因吗?思考后,可以把你的想法写在留言区。</p>
<p>下一课时,我将讲解 Docker 的架构设计以及 Docker 的三大核心概念。</p>
</div>
</div>
<div>
<div style="float: left">
<a href="/专栏/由浅入深吃透 Docker-完/00 溯本求源,吃透 Docker.md.html">上一页</a>
</div>
<div style="float: right">
<a href="/专栏/由浅入深吃透 Docker-完/02 核心概念:镜像、容器、仓库,彻底掌握 Docker 架构核心设计理念.md.html">下一页</a>
</div>
</div>
</div>
</div>
</div>
</div>
<a class="off-canvas-overlay" onclick="hide_canvas()"></a>
</div>
<script defer src="https://static.cloudflareinsights.com/beacon.min.js/v652eace1692a40cfa3763df669d7439c1639079717194" integrity="sha512-Gi7xpJR8tSkrpF7aordPZQlW2DLtzUlZcumS8dMQjwDHEnw9I7ZLyiOj/6tZStRBGtGgN6ceN6cMH8z7etPGlw==" data-cf-beacon='{"rayId":"70997b393b243cfa","version":"2021.12.0","r":1,"token":"1f5d475227ce4f0089a7cff1ab17c0f5","si":100}' crossorigin="anonymous"></script>
</body>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-NPSEEVD756"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag('js', new Date());
gtag('config', 'G-NPSEEVD756');
var path = window.location.pathname
var cookie = getCookie("lastPath");
console.log(path)
if (path.replace("/", "") === "") {
if (cookie.replace("/", "") !== "") {
console.log(cookie)
document.getElementById("tip").innerHTML = "<a href='" + cookie + "'>跳转到上次进度</a>"
}
} else {
setCookie("lastPath", path)
}
function setCookie(cname, cvalue) {
var d = new Date();
d.setTime(d.getTime() + (180 * 24 * 60 * 60 * 1000));
var expires = "expires=" + d.toGMTString();
document.cookie = cname + "=" + cvalue + "; " + expires + ";path = /";
}
function getCookie(cname) {
var name = cname + "=";
var ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i].trim();
if (c.indexOf(name) === 0) return c.substring(name.length, c.length);
}
return "";
}
</script>
</html>