mirror of
https://github.com/zhwei820/learn.lianglianglee.com.git
synced 2025-09-17 08:46:40 +08:00
905 lines
25 KiB
HTML
905 lines
25 KiB
HTML
<!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-<VERSION_STRING> docker-ce-cli-<VERSION_STRING> 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 官方仓库下载此镜像,然后运行它。最后我们看到该镜像输出 "Hello from Docker!" 并退出。</p>
|
||
|
||
<blockquote>
|
||
|
||
<p>安装完成后默认 docker 命令只能以 root 用户执行,如果想允许普通用户执行 docker 命令,需要执行以下命令 sudo groupadd docker && sudo gpasswd -a ${USER} docker && 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>
|
||
|