Docker 容器技术从入门到实战:生态系统、安装部署与架构详解

Docker 容器技术从入门到实战:生态系统、安装部署与架构详解

第1章 容器生态系统

摘要:本文系统讲解 Docker 容器技术,从容器生态系统的核心技术、平台技术与支持技术入手,帮助读者建立整体认知;随后以 CentOS Stream 8 为实验环境,逐步演示 Docker 的安装、镜像加速器配置(阿里云/华为云)以及第一个容器的运行;最后深入剖析 Docker 的 Client/Server 架构、核心组件(镜像、容器、仓库)及其协作流程,并通过容器与虚拟机的对比,阐明容器轻量、可移植、启动快的核心优势。

001 了解容器技术

  1. 系统讲解当前最流行的容器技术。
    从容器的整个生态环境到各个具体的技术,从整体到细节逐一讨论。
  2. 重实践并兼顾理论。
    从实际操作的角度带领大家学习容器技术。

为什么要写这个?

简单回答是:容器技术非常热门,但门槛高

容器技术是继大数据和云计算之后又一炙手可热的技术,而且未来相当一段时间内都会非常流行。

对 IT 行业来说,这是一项非常有价值的技术。而对 IT 从业者来说,掌握容器技术是市场的需要,也是提升自我价值的重要途径。

现在以 Docker 为代表的容器技术来了,而且关注度越来越高,这一点可以从 google 趋势 中 Docker 的搜索上升趋势(蓝色曲线)中清楚看到。


002 容器生态系统

对于像容器这类平台级别的技术,通常涉及的知识范围会很广,相关的软件,解决方案也会很多,初学者往往容易迷失。

那怎么办呢?

我们可以从生活经验中寻找答案。

当我们去陌生城市旅游想了解一下这个城市一般我们会怎么做?

我想大部分人应该会打开手机看一下这个城市的地图:

  1. 城市大概的位置和地理形状是什么?
  2. 都由哪几个区或县组成?
  3. 主要的交通干道是哪几条?

同样的道理,学习容器技术我们可以先从天上鸟瞰一下:

  1. 容器生态系统包含哪些不同层次的技术?
  2. 不同技术之间是什么关系?
  3. 哪些是核心技术哪些是辅助技术?

首先得对容器技术有个整体认识,之后我们的学习才能够有的放矢,才能够分清轻重缓急,做到心中有数,这样就不容易迷失了。

接下来我会根据自己的经验帮大家规划一条学习路线,一起探索容器生态系统。

学习新技术得到及时反馈是非常重要的,所以我们马上会搭建实验环境,并运行第一个容器,感受什么是容器。

千里之行始于足下,让我们从了解生态系统开始吧。

鸟瞰容器生态系统

一谈到容器,大家都会想到 Docker。

Docker 现在几乎是容器的代名词。确实,是 Docker 将容器技术发扬光大。同时,大家也需要知道围绕 Docker 还有一个生态系统。Docker 是这个生态系统的基石,但完善的生态系统才是保障 Docker 以及容器技术能够真正健康发展的决定因素。

大致来看,容器生态系统包含核心技术、平台技术和支持技术。

下面分别介绍。

容器核心技术

容器核心技术是指能够让 container 在 host os上运行起来的那些技术。

这些技术包括容器规范、容器 runtime、容器管理工具、容器定义工具、Registry 以及 容器 OS,下面分别介绍。

容器规范

容器不光是 Docker,还有其他容器,比如 CoreOS 的 rkt、红帽公司podman、containerd。为了保证容器生态的健康发展,保证不同容器之间能够兼容,包含 Docker、CoreOS、Google在内的若干公司共同成立了一个叫 Open Container Initiative(OCI) 的组织,其目是制定开放的容器规范。

目前 OCI 发布了两个规范:runtime spec 和 image format spec。

有了这两个规范,不同组织和厂商开发的容器能够在不同的 runtime 上运行。这样就保证了容器的可移植性和互操作性。

容器 runtime

runtime 是容器真正运行的地方。runtime 需要跟操作系统 kernel 紧密协作,为容器提供运行环境。

如果大家用过 Java,可以这样来理解 runtime 与容器的关系:

Java 程序就好比是容器,JVM 则好比是 runtime。JVM 为 Java 程序提供运行环境。同样的道理,容器只有在 runtime 中才能运行。

lxc、runc 和 rkt 是目前主流的三种容器 runtime。

lxc 是 Linux 上老牌的容器 runtime。Docker 最初也是用 lxc 作为 runtime。

runc 是 Docker 自己开发的容器 runtime,符合 oci 规范,也是现在 Docker 的默认 runtime。

rkt 是 CoreOS 开发的容器 runtime,符合 oci 规范,因而能够运行 Docker 的容器。

容器管理工具

光有 runtime 还不够,用户得有工具来管理容器啊。容器管理工具对内与 runtime 交互,对外为用户提供 interface,比如 CLI。这就好比除了 JVM,还得提供 java 命令让用户能够启停应用不是。

lxd 是 lxc 对应的管理工具。

runc 的管理工具是 docker engine。docker engine 包含后台 deamon 和 cli 两个部分。我们通常提到 Docker,一般就是指的 docker engine。

rkt 的管理工具是 rkt cli。

容器定义工具

容器定义工具允许用户定义容器的内容和属性,这样容器就能够被保存,共享和重建。

docker image 是 docker 容器的模板,runtime 依据 docker image 创建容器。

dockerfile 是包含若干命令的文本文件,可以通过这些命令创建出 docker image。

ACI (App Container Image) 与 docker image 类似,只不过它是由 CoreOS 开发的 rkt 容器的 image 格式。

Registry

容器是通过 image 创建的,需要有一个仓库来统一存放 image,这个仓库就叫做 Registry。

企业可以用 Docker Registry 构建私有的 Registry。

Docker Hub(https://hub.docker.com) 是 Docker 为公众提供的托管 Registry,上面有很多现成的 image,为 Docker 用户提供了极大的便利。

Quay.iohttps://quay.io/)是另一个公共托管 Registry,提供与 Docker Hub 类似的服务。

容器 OS

由于有容器 runtime,几乎所有的 Linux、MAC OS 和 Windows 都可以运行容器。但这不并没有妨碍容器 OS 的问世。

容器 OS 是专门运行容器的操作系统。与常规 OS 相比,容器 OS 通常体积更小,启动更快。因为是为容器定制的 OS,通常它们运行容器的效率会更高。

目前已经存在不少容器 OS,CoreOS、atomic 和 ubuntu core 是其中的杰出代表。

下一节继续介绍容器平台技术和容器支持技术。


003 容器生态系统(续)

容器生态系统包含核心技术、平台技术和支持技术三个方面。上一节我们讨论了核心技术,今天讨论另外两个部分。

容器平台技术

容器核心技术使得容器能够在单个 host 上运行。而容器平台技术能够让容器作为集群在分布式环境中运行。

容器平台技术包括容器编排引擎、容器管理平台和基于容器的 PaaS。

容器编排引擎

基于容器的应用一般会采用微服务架构。在这种架构下,应用被划分为不同的组件,并以服务的形式运行在各自的容器中,通过 API 对外提供服务。为了保证应用的高可用,每个组件都可能会运行多个相同的容器。这些容器会组成集群,集群中的容器会根据业务需要被动态地创建、迁移和销毁。

大家可以看到,这样一个基于微服务架构的应用系统实际上是一个动态的可伸缩的系统。这对我们的部署环境提出了新的要求,我们需要有一种高效的方法来管理容器集群。而这,就是容器编排引擎要干的工作。

所谓编排(orchestration),通常包括容器管理、调度、集群定义和服务发现等。通过容器编排引擎,容器被有机的组合成微服务应用,实现业务需求。

docker swarm 是 Docker 开发的容器编排引擎。

kubernetes 是 Google 领导开发的开源容器编排引擎,同时支持 Docker 和 CoreOS 容器。

mesos 是一个通用的集群资源调度平台,mesos 与 marathon 一起提供容器编排引擎功能。

以上三者是当前主流的容器编排引擎。

容器管理平台

容器管理平台是架构在容器编排引擎之上的一个更为通用的平台。通常容器管理平台能够支持多种编排引擎,抽象了编排引擎的底层实现细节,为用户提供更方便的功能,比如 application catalog 和一键应用部署等。

Rancher 和 ContainerShip 是容器管理平台的典型代表。

基于容器的 PaaS

基于容器的 PaaS 为微服务应用开发人员和公司提供了开发、部署和管理应用的平台,使用户不必关心底层基础设施而专注于应用的开发。

Deis、Flynn 和 Dokku 都是开源容器 PaaS 的代表。

容器支持技术

下面这些技术被用于支持基于容器的基础设施。

容器网络

容器的出现使网络拓扑变得更加动态和复杂。用户需要专门的解决方案来管理容器与容器,容器与其他实体之间的连通性和隔离性。

docker network 是 Docker 原生的网络解决方案。除此之外,我们还可以采用第三方开源解决方案,例如 flannel、weave 和 calico。不同的方案设计和实现方式不同,各有优势和特定,我们可以根据实际需要来选型。

服务发现

动态变化是微服务应用的一大特点。当负载增加时,集群会自动创建新的容器;负载减小,多余的容器会被销毁。容器也会根据 host 的资源使用情况在不同 host 中迁移,容器的 IP 和端口也会随之发生变化。

在这种动态的环境下,必须要有一种机制让 client 能够知道如何访问容器提供的服务。这就是服务发现技术要完成的工作。

服务发现会保存容器集群中所有微服务最新的信息,比如 IP 和端口,并对外提供 API,提供服务查询功能。

etcd、consul 和 zookeeper 是服务发现的典型解决方案。

监控

监控对于基础架构非常重要,而容器的动态特征对监控提出更多挑战。

针对容器环境,已经涌现出很多监控工具和方案。

docker ps/top/stats 是 Docker 原生的命令行监控工具。除了命令行,Docker 也提供了 stats API,用户可以通过 HTTP 请求获取容器的状态信息。

sysdig、cAdvisor/Heapster 和 Weave Scope 是其他开源的容器监控方案。

数据管理

容器经常会在不同的 host 之间迁移,如何保证持久化数据也能够动态迁移,是 Flocker 这类数据管理工具提供的能力。

日志管理

日志为问题排查和事件管理提供了重要依据。

docker logs 是 Docker 原生的日志工具。而 logspout 对日志提供了路由功能,它可以收集不同容器的日志并转发给其他工具进行后处理。

安全性

对于年轻的容器,安全性一直是业界争论的焦点。

OpenSCAP 能够对容器镜像进行扫描,发现潜在的漏洞。


004 安装docker

环境选择

容器需要管理工具、runtime 和操作系统,我们的选择如下:

  1. 管理工具 - Docker Engine,Docker 最流行使用最广泛。
  2. runtime - runc,Docker 的默认 runtime
  3. 操作系统 - CentOS Stream8

安装操作系统

基于CentOS-Stream-8模板制作.pdf这个实验手册做出来的模板克隆一个虚拟机命名为docker,并配置静态IP 192.168.108.30,主机名改为docker

bash 复制代码
[root@localhost ~]# hostnamectl set-hostname docker
[root@localhost ~]# nmcli connection modify ens160 ipv4.method manual ipv4.addresses 192.168.108.30/24 ipv4.gateway 192.168.108.2 ipv4.dns 192.168.108.2 autoconnect yes
[root@localhost ~]# nmcli con up ens160

安装 Docker

Docker 支持几乎所有的 Linux 发行版,也支持 Mac 和 Windows。各操作系统的安装方法可以访问:https://docs.docker.com/engine/installation/

卸载旧版本(可选)

bash 复制代码
[root@docker ~]# yum remove docker-ce

安装必要工具

bash 复制代码
# devicemapper 存储驱动已经在 docker 18.09 版本中被废弃,所以在后续的安Docker装中无需安装devicemapper支持。
[root@localhost ~]# yum install -y yum-utils device-mapper-persistent-data lvm2 vim      
[root@localhost ~]# yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
Adding repo from: https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
[root@localhost ~]# yum makecache
Docker CE Stable - x86_64                                                                             57 kB/s |  66 kB     00:01
CentOS Stream 8 - BaseOS                                                                             8.3 kB/s | 3.9 kB     00:00
CentOS Stream 8 - AppStream                                                                          9.8 kB/s | 4.4 kB     00:00
Metadata cache created.

allinone部署

安装软件

bash 复制代码
[root@docker ~]# yum install -y docker-ce

配置服务

bash 复制代码
[root@docker ~]# systemctl enable docker.service --now

验证安装

查看docker版本

bash 复制代码
[root@docker ~]# docker --version
Docker version 26.1.3, build b72abbb

验证docker状态

bash 复制代码
[root@docker ~]# systemctl status docker
● docker.service - Docker Application Container Engine
   Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
   Active: active (running) since Wed 2025-09-03 13:51:07 CST; 36s ago
     Docs: https://docs.docker.com
 Main PID: 1813 (dockerd)
    Tasks: 10
   Memory: 135.7M
   CGroup: /system.slice/docker.service
           └─1813 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
配置镜像加速器(阿里云)

阿里云官网:阿里云-计算,为了无法计算的价值

参考操作文档,操作

bash 复制代码
[root@docker ~]# sudo mkdir -p /etc/docker

[root@docker ~]# sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://spcqvmfn.mirror.aliyuncs.com"]
}
EOF

[root@docker ~]# sudo systemctl daemon-reload
[root@docker ~]# sudo systemctl restart docker

#检查镜像加速器配置
[root@docker ~]# docker info
Client: Docker Engine - Community
 Version:    26.1.3
 Context:    default
 Debug Mode: false
 Plugins:
  buildx: Docker Buildx (Docker Inc.)
    Version:  v0.14.0
    Path:     /usr/libexec/docker/cli-plugins/docker-buildx
  compose: Docker Compose (Docker Inc.)
    Version:  v2.27.0
    Path:     /usr/libexec/docker/cli-plugins/docker-compose

Server:
 Containers: 0
  Running: 0
  Paused: 0
  Stopped: 0
 Images: 0
 Server Version: 26.1.3
 Storage Driver: overlay2
  Backing Filesystem: xfs
  Supports d_type: true
  Using metacopy: false
  Native Overlay Diff: true
  userxattr: false
 Logging Driver: json-file
 Cgroup Driver: cgroupfs
 Cgroup Version: 1
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local splunk syslog
 Swarm: inactive
 Runtimes: io.containerd.runc.v2 runc
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: 8b3b7ca2e5ce38e8f31a34f35b2b68ceb8470d89
 runc version: v1.1.12-0-g51d5e94
 init version: de40ad0
 Security Options:
  seccomp
   Profile: builtin
 Kernel Version: 4.18.0-553.6.1.el8.x86_64
 Operating System: CentOS Stream 8
 OSType: linux
 Architecture: x86_64
 CPUs: 4
 Total Memory: 7.486GiB
 Name: docker
 ID: 96160847-9a97-40f4-997c-d12efaaef738
 Docker Root Dir: /var/lib/docker
 Debug Mode: false
 Experimental: false
 Insecure Registries:
  127.0.0.0/8
 Registry Mirrors:
  `https://spcqvmfn.mirror.aliyuncs.com/               <---看这
 Live Restore Enabled: false
配置镜像加速器(华为云)

看镜像加速器如何使用

bash 复制代码
[root@docker ~]# vi /etc/docker/daemon.json
{
    "registry-mirrors": [ "https://054b8ac70e8010d90f2ac00ef29e6580.mirror.swr.myhuaweicloud.com" ]
}
# 按"Esc",输入:wq保存并退出。

#重启容器引擎
[root@docker ~]# systemctl restart docker

#确认配置结果
[root@docker ~]# docker info
Client: Docker Engine - Community
 Version:    26.1.3
 Context:    default
 Debug Mode: false
 Plugins:
  buildx: Docker Buildx (Docker Inc.)
    Version:  v0.14.0
    Path:     /usr/libexec/docker/cli-plugins/docker-buildx
  compose: Docker Compose (Docker Inc.)
    Version:  v2.27.0
    Path:     /usr/libexec/docker/cli-plugins/docker-compose

Server:
 Containers: 0
  Running: 0
  Paused: 0
  Stopped: 0
 Images: 0
 Server Version: 26.1.3
 Storage Driver: overlay2
  Backing Filesystem: xfs
  Supports d_type: true
  Using metacopy: false
  Native Overlay Diff: true
  userxattr: false
 Logging Driver: json-file
 Cgroup Driver: cgroupfs
 Cgroup Version: 1
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local splunk syslog
 Swarm: inactive
 Runtimes: io.containerd.runc.v2 runc
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: 8b3b7ca2e5ce38e8f31a34f35b2b68ceb8470d89
 runc version: v1.1.12-0-g51d5e94
 init version: de40ad0
 Security Options:
  seccomp
   Profile: builtin
 Kernel Version: 4.18.0-553.6.1.el8.x86_64
 Operating System: CentOS Stream 8
 OSType: linux
 Architecture: x86_64
 CPUs: 4
 Total Memory: 7.486GiB
 Name: docker
 ID: 96160847-9a97-40f4-997c-d12efaaef738
 Docker Root Dir: /var/lib/docker
 Debug Mode: false
 Experimental: false
 Insecure Registries:
  127.0.0.0/8
 Registry Mirrors:
  `https://054b8ac70e8010d90f2ac00ef29e6580.mirror.swr.myhuaweicloud.com/   <---看这
 Live Restore Enabled: false

运行第一个容器

环境就绪,马上运行第一个容器,执行命令:

bash 复制代码
[root@docker ~]# docker run hello-world

其过程可以简单的描述为:

  1. 从本地查找hello-wrold镜像,没找到
  2. 从 Docker Hub 下载hello-world镜像。
  3. 启动hello-world容器。

清空刚才的实验环境:

bash 复制代码
[root@docker ~]# docker rm -f $(docker ps -aq)        #删除所有容器

[root@docker ~]# docker rmi -f hello-world           #删除镜像hello-world

此刻docker环境没有问题了,关机拍摄快照

运行第二个容器

bash 复制代码
[root@docker ~]# docker run -d -p 80:80 httpd
Unable to find image 'httpd:latest' locally               
latest: Pulling from library/httpd
852e50cd189d: Pull complete 
67d51c33d390: Pull complete 
b0ad2a3b9567: Pull complete 
136f1f71f30c: Pull complete 
01f8ace29294: Pull complete 
Digest: sha256:fddc534b7f6bb6197855be559244adb11907d569aae1283db8e6ce8bb8f6f456
Status: Downloaded newer image for httpd:latest
817f24cca3514568f9b7a7cac6f183734077fb74caf4c62502acd2a4d0d29520

其过程可以简单的描述为:

  1. 从 Docker Hub 下载 httpd 镜像。镜像中已经安装好了 Apache HTTP Server。
  2. 启动 httpd 容器,并将容器的 80 端口映射到 host 的 80 端口。

下面我们可以通过浏览器验证容器是否正常工作。在浏览器中输入 http://your host os IP

bash 复制代码
[root@docker ~]# curl 192.168.108.30
<html><body><h1>It works!</h1></body></html>

可以访问容器的 http 服务了,第一个容器运行成功!我们轻轻松松就拥有了一个 WEB 服务器。

---

005 docker C/S分离部署

基于CentOS-Stream-8模板制作.pdf这个实验手册做出来的模板克隆虚拟机命名为docker_client和docker_server

docker server端配置

配置ip 192.168.108.30

配置hostname docker_server

bash 复制代码
[root@localhost ~]# hostnamectl set-hostname docker_server
[root@localhost ~]# nmcli connection modify ens160 ipv4.method manual ipv4.addresses 192.168.108.30/24 ipv4.gateway 192.168.108.2 ipv4.dns 192.168.108.2 autoconnect yes
[root@localhost ~]# nmcli con up ens160

安装软件

bash 复制代码
[root@docker_server ~]# yum install -y yum-utils device-mapper-persistent-data lvm2 vim      
[root@localhost ~]# yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
Adding repo from: https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
[root@docker_server ~]# yum makecache
[root@docker_server ~]# yum install -y docker-ce  
[root@docker_server ~]# systemctl enable docker.service --now
[root@docker_server ~]# vi /etc/docker/daemon.json
{
    "registry-mirrors": [ "https://054b8ac70e8010d90f2ac00ef29e6580.mirror.swr.myhuaweicloud.com" ]
}
# 按"Esc",输入:wq保存并退出。

#重启容器引擎
[root@docker_server ~]# systemctl restart docker

配置服务

bash 复制代码
[root@docker_server ~]# vim /usr/lib/systemd/system/docker.service
# 在ExecStart参数中最后添加 -H tcp://0.0.0.0:2375,docker默认监听2375
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock -H tcp://0.0.0.0:2375
[root@docker_server ~]# systemctl daemon-reload
[root@docker_server ~]# systemctl restart docker.service
[root@docker_server ~]# systemctl stop firewalld

配置效果如下

验证

bash 复制代码
[root@docker_server ~]# yum install lsof

[root@docker_server ~]# lsof -i :2375
COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
dockerd 5440 root    3u  IPv6  44991      0t0  TCP *:docker (LISTEN)

docker_client端

配置ip 192.168.108.31

bash 复制代码
[root@localhost ~]# hostnamectl set-hostname docker_client
[root@localhost ~]# nmcli connection modify ens160 ipv4.method manual ipv4.addresses 192.168.108.31/24 ipv4.gateway 192.168.108.2 ipv4.dns 192.168.108.2 autoconnect yes
[root@localhost ~]# nmcli con up ens160

只安装docker客户端

bash 复制代码
[root@docker-client ~]# yum install -y yum-utils device-mapper-persistent-data lvm2 vim      
[root@docker-client ~]# yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
Adding repo from: https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
[root@docker-client ~]# yum makecache
[root@docker-client ~]# yum install -y docker-ce-cli

验证

bash 复制代码
[root@docker_client ~]# docker run hello-world          #client直接执行报错,没有装服务端
docker: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?.
See 'docker run --help'.

# client端连接server端执行命令
[root@docker-client ~]# docker -H 192.168.108.30 run hello-world

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/
 
[root@docker-client ~]# docker -H 192.168.108.30 images 
REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
hello-world   latest    d2c94e258dcb   17 months ago   13.3kB
#这里也可以切换到Server端查看现象

说明:client只做管理,image和container存储在server端。


第2章 容器架构

006 容器What,Why,How

学习任何东西都可以按照3W的框架进行,容器技术也是一样,先回答 What、Why 和 How 这三个问题。

容器发展史

  • 1979年,在Unix V7 的开发过程中,引入Chroot Jail以及Chroot系统调用Chroot jail被用于"Change Root",它被认为是最早的容器化技术之一。它允许您将进程及其子进程与操作系统的其余部分隔离开来。这种隔离的唯一问题是根进程(root process)可以轻松地退出chroot。它从未考虑实现安全机制。
  • 1982年,Chroot加入BSD。
  • 2000年,在FreeBSD OS中引入FreeBSD Jail,旨在为简单的Chroot文件隔离带来更多安全性。FreeBSD Jail允许管理员将FreeBSD OS划分为几个独立的小型系统 - 称为"jails",还可以为每个小型系统分配IP地址。
  • 2001年,Linux内核具有操作系统级的虚拟化的功能以后推出了Linux VServer。它使用了类似chroot的机制与"安全上下文"("security context")以及操作系统虚拟化(容器化)相结合来提供虚拟化解决方案,允许您在单个Linux发行版上运行多个Linux发行版。
  • 2004年,Solaris Containers问世,它使用系统资源控制和"区域"(zone)实现边界分离。
  • 2006年,Google推出Process Containers,旨在限制,计算和隔离一组进程的资源使用(CPU,内存,磁盘I/O,网络)。2007年,命名为控制组-cgroups,最终合并到Linux内核2.6.24。
  • 2008年,LXC(LinuX Containers)是第一个Linux容器管理器,使用cgroups和命名空间(namespace)在单个Linux内核上运行多个容器。
  • 2013年,Docker推出了的第一个版本。在LXC的基础上,Docker进一步优化了容器的使用体验。后来用自己的库libcontainer替换了该容器管理器。
  • 2014年,Google推出容器LMCTFY(Let me contain that for you),谷歌容器栈的开源版本,提供Linux应用程序容器。谷歌工程师一直在与Docker合作libcontainer,并将核心概念和抽象移植到libcontainer。因此没有积极开发LMCTFY项目,未来LMCTFY项目的核心可能会被libcontainer取代。谷歌是容器化行业的领导者。谷歌的一切都在容器上运行。每周有超过20亿个容器在Google基础架构上运行。
  • 2014年12月,CoreOS发布并开始支持rkt。
What - 什么是容器?

容器是一种轻量级、可移植、自包含的软件打包技术,使应用程序可以在几乎任何地方以相同的方式运行。开发人员在自己笔记本上创建并测试好的容器,无需任何修改就能够在生产系统的虚拟机、物理服务器或公有云主机上运行。

容器与虚拟机

谈到容器,就不得不将它与虚拟机进行对比,因为两者都是为应用提供封装和隔离。

容器由两部分组成:

  1. 应用程序本身
  2. 依赖:比如应用程序需要的库或其他软件

容器在 Host 操作系统的用户空间中运行,与操作系统的其他进程隔离。这一点显著区别于的虚拟机。

传统的虚拟化技术,比如 VMWare, KVM, Xen,目标是创建完整的虚拟机。为了运行应用,除了部署应用本身及其依赖(通常几十 MB),还得安装整个操作系统(几十 GB)。

下图展示了二者的区别。

虚拟机 容器
启动速度 数秒至数十秒 秒甚至毫秒启动
系统内核 不共享内核 共享内核
实现技术 依赖虚拟化技术实现,由Hypervisor层实现对资源的隔离 利用Linux内核技术Namespace/Cgroup等实现。
隔离效果 系统资源级别的隔离 进程级别的隔离
资源消耗(性能) 使用虚拟化技术,就会有额外的资源消耗和占用 容器中的应用只是宿主机上的一个普通进程
资源调用 (敏捷性) 应用进程需经过Hypervisor的拦截和处理,才能调用系统资源 应用进程直接由宿主机OS管理
运行数量 一台服务器上一般不超过100台虚拟机 一台服务器上能启动1000+容器
应用 用于硬件资源划分 DevOps、微服务等
镜像 非分层镜像 分层镜像

如图所示,由于所有的容器共享同一个 Host OS,这使得容器在体积上要比虚拟机小很多。另外,启动容器不需要启动整个操作系统,所以容器部署和启动速度更快,开销更小,也更容易迁移。

Why - 为什么需要容器?

为什么需要容器?容器到底解决的是什么问题?

简要的答案是:容器使软件具备了超强的可移植能力

容器解决的问题

我们来看看今天的软件开发面临着怎样的挑战?

如今的系统在架构上较十年前已经变得非常复杂了。以前几乎所有的应用都采用三层架构(Presentation/Application/Data),系统部署到有限的几台物理服务器上(Web Server/Application Server/Database Server)。

而今天,开发人员通常使用多种服务(比如 MQ,Cache,DB)构建和组装应用,而且应用很可能会部署到不同的环境,比如虚拟服务器,私有云和公有云。

一方面应用包含多种服务,这些服务有自己所依赖的库和软件包;另一方面存在多种部署环境,服务在运行时可能需要动态迁移到不同的环境中。这就产生了一个问题:

如何让每种服务能够在所有的部署环境中顺利运行?

于是我们得到了下面这个矩阵:

各种服务和环境通过排列组合产生了一个大矩阵。开发人员在编写代码时需要考虑不同的运行环境,运维人员则需要为不同的服务和平台配置环境。对他们双方来说,这都是一项困难而艰巨的任务。

如何解决这个问题呢?

聪明的技术人员从传统的运输行业找到了答案。

几十年前,运输业面临着类似的问题。

每一次运输,货主与承运方都会担心因货物类型的不同而导致损失,比如几个铁桶错误地压在了一堆香蕉上。另一方面,运输过程中需要使用不同的交通工具也让整个过程痛苦不堪:货物先装上车运到码头,卸货,然后装上船,到岸后又卸下船,再装上火车,到达目的地,最后卸货。一半以上的时间花费在装、卸货上,而且搬上搬下还容易损坏货物。

这同样也是一个 NxM 的矩阵。

幸运的是,集装箱的发明解决这个难题。

任何货物,无论钢琴还是保时捷,都被放到各自的集装箱中。集装箱在整个运输过程中都是密封的,只有到达最终目的地才被打开。标准集装箱可以被高效地装卸、重叠和长途运输。现代化的起重机可以自动在卡车、轮船和火车之间移动集装箱。集装箱被誉为运输业与世界贸易最重要的发明。

Docker 将集装箱思想运用到软件打包上,为代码提供了一个基于容器的标准化运输系统。Docker 可以将任何应用及其依赖打包成一个轻量级、可移植、自包含的容器。容器可以运行在几乎所有的操作系统上。

其实,"集装箱" 和 "容器" 对应的英文单词都是 "Container"。"容器" 是国内约定俗成的叫法,可能是因为容器比集装箱更抽象,更适合软件领域的原故吧。

我个人认为:在老外的思维中,"Container" 只用到了集装箱这一个意思,Docker 的 Logo 不就是一堆集装箱吗?

Docker 的特性

我们可以看看集装箱思想是如何与 Docker 各种特性相对应的。

特性 集装箱 Docker
打包对象 几乎任何货物 任何软件及其依赖
硬件依赖 标准形状和接口允许集装箱被装卸到各种交通工具,整个运输过程无需打开 容器无需修改便可运行在几乎所有的平台上 -- 虚拟机、物理机、公有云、私有云
隔离性 集装箱可以重叠起来一起运输,香蕉再也不会被铁桶压烂了 资源、网络、库都是隔离的,不会出现依赖问题
自动化 标准接口使集装箱很容易自动装卸和移动 提供 run, start, stop 等标准化操作,非常适合自动化
高效性 无需开箱,可在各种交通工具间快速搬运 轻量级,能够快速启动和迁移
职责分工 货主只需考虑把什么放到集装箱里;承运方只需关心怎样运输集装箱 开发人员只需考虑怎么写代码;运维人员只需关心如何配置基础环境

容器的优势

对于开发人员 - Build Once, Run Anywhere

容器意味着环境隔离和可重复性。开发人员只需为应用创建一次运行环境,然后打包成容器便可在其他机器上运行。另外,容器环境与所在的 Host 环境是隔离的,就像虚拟机一样,但更快更简单。

对于运维人员 - Configure Once, Run Anything

只需要配置好标准的 runtime 环境,服务器就可以运行任何容器。这使得运维人员的工作变得更高效,一致和可重复。容器消除了开发、测试、生产环境的不一致性。

How - 容器是如何工作的?

从下节开始我们将学习容器核心知识的最主要部分。首先会介绍 Docker 的架构,然后分章节详细讨论 Docker 的镜像、容器、网络和存储。

容器与虚拟机比较

谈到容器,就不得不将它与虚拟机进行对比,因为两者都是为应用提供封装和隔离。

容器由两部分组成:

  1. 应用程序本身
  2. 依赖:比如应用程序需要的库或其他软件

容器在 Host 操作系统的用户空间中运行,与操作系统的其他进程隔离。这一点显著区别于的虚拟机。

传统的虚拟化技术,比如 VMWare, KVM, Xen,目标是创建完整的虚拟机。为了运行应用,除了部署应用本身及其依赖(通常几十 MB),还得安装整个操作系统(几十 GB)。

下图展示了二者的区别:

如图所示:

  • 所有的容器共享同一个 Host OS,这使得容器在体积上要比虚拟机小很多。
  • 另启动容器不需要启动整个操作系统,容器部署和启动速度更快,开销更小,也更容易迁移。

容器可以在核心CPU本地运行指令,而不需要任何专门的解释机制。与虚拟化相比,这样既不需要指令级模拟,也不需要即时编译。

特性 容器 虚拟机
启动速度 秒级 分钟级
性能 接近原生 较弱
内存代价 很小 较多
硬盘使用 一般为MB 一般为GB
运行密度 单击支持上千个容器 一般几十个
隔离性 安全隔离 完全隔离
迁移性 优秀 一般

Docker介绍

Docker是基于Go语言实现的开源容器项目,诞生于2013年年初,最初发起者是dotCloud公司。Docker自开源后受到广泛的关注和讨论,逐渐形成了围绕Docker容器的生态体系。由于Docker在业界造成的影响力实在太大,dotCloud公司后来也直接改名为Docker Inc,并专注于 Docker相关技术和产品的开发。

Docker提供了各种容器管理工具 (如分发、版本、移植等),让用户无需关注底层的操作,可以更简单明了地管理和使用容器;其次,Docker引入分层文件系统构建和高效的镜像机制降低了迁移难度,极大地提升了用户体验。用户操作Docker容器就像操作应用自身一样简单。

简单地讲,可以将Docker容器理解为一种轻量级的沙盒(sandbox)。**每个容器内运行着一个应用,不同的容器相互隔离,容器之间也可以通过网络互相通信。**容器的创建和停止都十分快速,几乎跟创建和终止原生应用一致;另外,容器自身对系统资源的额外需求也十分有限,远远低于传统虚拟机。很多时候,甚至直接把容器当作应用本身也没有任何问题。

Docker版本

Docker CE在17.03版本之前叫Docker Engine,Docker Engine的版本号范围:0.1.0~1.13.1。

在2017年3月2日,docker团队宣布企业版Docker Enterprise Edition(EE)发布.为了一致,免费的Docker Engine改名为Docker Community Edition(CE),并且采用基于时间的版本号方案.就在这一天,Docker EE和Docker CE的17.03版本发布,这也是第一个采用新的版本号方案的版本。

Docker CE/EE每个季度发布一次季度版本,也就是说每年会发布4个季度版本,17.03,17.06,17.09,17.12就是2017年的4个季度版本的版本号,同时Docker CE每个月还会发布一个EDGE版本,比如17.04,17.05,17.07,17.08,17.10,17.11.

Docker CE季度版本自发布后会有4个月的维护期;Docker EE季度版本自发布后会有12个月的维护期.

在基于时间的发布方案中,版本号格式为:YY.MM.,YY.MM代表年月,patch代表补丁号,从0开始,在季度版本(如17.03)的维护期内,bug修复相关的更新会以patch递增的方式发布,比如17.03.0->17.03.1->17.03.2.

Docker核心概念

Docker的大部分操作都围绕着它的三大核心概念------镜像、容器和仓库而展开。

Docker镜像

Docker镜像类似于虚拟机镜像,可以将它理解为一个只读的模板。例如,一个镜像可以包含一个基本的操作系统环境,里面仅安装了Apache应用程序(或用户需要的其他软件)。可以把它称为一个Apache镜像。镜像是创建Docker容器的基础。通过版本管理和增量的文件系统,Docker提供了一套十分简单的机制创建和更新现有的镜像,用户甚至可以从网上下载一个已经做好的应用镜像,并直接使用。

Docker容器

Docker容器类似于一个轻量级的沙箱,Docker利用容器来运行和隔离应用。容器是从镜像创建的应用运行实例。可以将其启动、开始、停止、删除,而这些容器都是彼此相互隔离的、互不可见的。可以把容器看做是一个简易版的Linux系统环境(包括root用户权限、进程空间、用户空间和网络空间等)以及运行在其中的应用程序打包而成的盒子。

Docker仓库

Docker仓库类似于代码仓库,它是Docker集中存放镜像文件的场所。仓库注册服务器存放着很多类镜像,每类镜像包括多个镜像文件,通过不同的标签(tag)来进行区分。例如存放Ubuntu操作系统镜像的分类中可能包括1804、1604、14.04、12.04等不同版本的镜像。

根据所存储的镜像公开分享与否,Docker仓库可以分为:

  • 公开仓库(Public)
  • 私有仓库(Private)

目前,最大的公开仓库是官方提供的Docker Hub,其中存放了数量庞大的镜像供用户下载。国内不少云服务提供商(如时速云、阿里云等)也提供了仓库的本地源,可以提供稳定的国内访问。

当然,用户如果不希望公开分享自己的镜像文件,Docker也支持用户在本地网络内创建一个只能自己访问的私有仓库。当用户创建了自己的镜像之后就可以使用push命令将它上传到指定的公有或者私有仓库。这样用户下次在另外一台机器上使用该镜像时,只需要将其从仓库上pull下来就可以了。

007 Docker架构详解

完整的Docker由以下几部分构成:

  • (1) **守护进程(Daemon):**Docker守护进程(dockerd)侦听Docker API请求并管理Docker对象,,如图像、容器、网络和卷。守护进程还可以与其他守护进程通信来管理Docker服务。
  • (2) REST API: 主要与Docker Daemon进行交互,比如Docker Cli或者直接调用REST API;
  • (3) 客户端(Docker Client): 它是与Docker交互的主要方式通过命令行接口(CLI)客户端(docker命令),客户机将命令通过REST API发送给并执行其命令;
  • (4) Register Repository 镜像仓库: Docker注册表存储Docker镜像,可以采用Docker Hub是公共注册仓库,或者采用企业内部自建的Harbor私有仓库;
  • (5) Image 镜像: 映像是一个只读模板,带有创建Docker容器的指令。映像通常基于另一个映像,还需要进行一些额外的定制,你可以通过Docker Hub公共镜像仓库进行拉取对应的系统或者应用镜像;
  • (6) Container 容器: 容器是映像的可运行实例。您可以使用Docker API或CLI创建、启动、停止、移动或删除容器。您可以将一个容器连接到一个或多个网络,将存储附加到它,甚至根据它的当前状态创建一个新映像。
  • (7) Services : Docker引擎支持集群模式服务允许您跨多个Docker守护进程()扩展管理容器,服务允许您定义所需的状态,例如在任何给定时间必须可用的服务副本的数量。默认情况下,服务在所有工作节点之间进行负载平衡。对于使用者来说Docker服务看起来是一个单独的应用程序;

Docker 的核心组件包括:

  1. Docker 客户端 - Client
  2. Docker 服务器 - Docker daemon
  3. Docker 镜像 - Image
  4. Registry
  5. Docker 容器 - Container

Docker 架构如下图所示:

Docker 采用的是 Client/Server 架构。客户端向服务器发送请求,服务器负责构建、运行和分发容器。客户端和服务器可以运行在同一个 Host 上,客户端也可以通过 socket 或 REST API 与远程的服务器通信。

Docker 内部具体实现:

  1. 用户是使用Docker Client与Docker Daemon建立通信,并发送请求给后者。
  2. Docker Daemon作为Docker架构中的主体部分,首先提供Docker Server的功能使其可以接受Docker Client的请求。
  3. Docker Engine执行Docker内部的一系列工作,每一项工作都是以一个Job的形式的存在。
  4. Job的运行过程中,当需要容器镜像时,则从DockerRegistry中下载镜像,并通过镜像管理驱动Graph driver将下载镜像以Graph的形式存储。
  5. 当需要为Docker创建网络环境时,通过网络管理驱动Networkdriver创建并配置Docker容器网络环境。
  6. 当需要限制Docker容器运行资源或执行用户指令等操作时,则通过Exec driver来完成。
  7. Libcontainer是一项独立的容器管理包,Networkdriver以及Execdriver都是通过Libcontainer来实现具体对容器进行的操作。

Docker 客户端

最常用的 Docker 客户端是 docker 命令。通过 docker 我们可以方便地在 Host 上构建和运行容器。

docker 支持很多操作(子命令),后面会逐步用到。

shell 复制代码
[root@docker ~]# docker

Usage:  docker [OPTIONS] COMMAND

A self-sufficient runtime for containers

Common Commands:
  run         Create and run a new container from an image
  exec        Execute a command in a running container
  ps          List containers
  build       Build an image from a Dockerfile
  pull        Download an image from a registry
  push        Upload an image to a registry
  images      List images
  login       Log in to a registry
  logout      Log out from a registry
  search      Search Docker Hub for images
  version     Show the Docker version information
  info        Display system-wide information

Management Commands:
  builder     Manage builds
  buildx*     Docker Buildx
  compose*    Docker Compose
  container   Manage containers
  context     Manage contexts
  image       Manage images
  manifest    Manage Docker image manifests and manifest lists
  network     Manage networks
  plugin      Manage plugins
  system      Manage Docker
  trust       Manage trust on Docker images
  volume      Manage volumes

Swarm Commands:
  swarm       Manage Swarm

Commands:
  attach      Attach local standard input, output, and error streams to a running container
  commit      Create a new image from a container's changes
  cp          Copy files/folders between a container and the local filesystem
  create      Create a new container
  diff        Inspect changes to files or directories on a container's filesystem
  events      Get real time events from the server
  export      Export a container's filesystem as a tar archive
  history     Show the history of an image
  import      Import the contents from a tarball to create a filesystem image
  inspect     Return low-level information on Docker objects
  kill        Kill one or more running containers
  load        Load an image from a tar archive or STDIN
  logs        Fetch the logs of a container
  pause       Pause all processes within one or more containers
  port        List port mappings or a specific mapping for the container
  rename      Rename a container
  restart     Restart one or more containers
  rm          Remove one or more containers
  rmi         Remove one or more images
  save        Save one or more images to a tar archive (streamed to STDOUT by default)
  start       Start one or more stopped containers
  stats       Display a live stream of container(s) resource usage statistics
  stop        Stop one or more running containers
  tag         Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
  top         Display the running processes of a container
  unpause     Unpause all processes within one or more containers
  update      Update configuration of one or more containers
  wait        Block until one or more containers stop, then print their exit codes

Global Options:
      --config string      Location of client config files (default "/root/.docker")
  -c, --context string     Name of the context to use to connect to the daemon (overrides
                           DOCKER_HOST env var and default context set with "docker context use")
  -D, --debug              Enable debug mode
  -H, --host list          Daemon socket to connect to
  -l, --log-level string   Set the logging level ("debug", "info", "warn", "error", "fatal")
                           (default "info")
      --tls                Use TLS; implied by --tlsverify
      --tlscacert string   Trust certs signed only by this CA (default "/root/.docker/ca.pem")
      --tlscert string     Path to TLS certificate file (default "/root/.docker/cert.pem")
      --tlskey string      Path to TLS key file (default "/root/.docker/key.pem")
      --tlsverify          Use TLS and verify the remote
  -v, --version            Print version information and quit

Run 'docker COMMAND --help' for more information on a command.

For more help on how to use Docker, head to https://docs.docker.com/go/guides/

除了 docker 命令行工具,用户也可以通过 REST API 与服务器通信。

Docker 服务器

Docker daemon 是服务器组件,以 Linux 后台服务的方式运行。

shell 复制代码
[root@docker ~]# systemctl status docker.service
● docker.service - Docker Application Container Engine
   Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
   Active: active (running) since Mon 2024-09-09 21:40:20 CST; 24h ago
     Docs: https://docs.docker.com
 Main PID: 2309 (dockerd)
    Tasks: 10
   Memory: 136.0M
   CGroup: /system.slice/docker.service
           └─2309 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

Sep 09 21:40:16 docker systemd[1]: Starting Docker Application Container Engine...
Sep 09 21:40:17 docker dockerd[2309]: time="2024-09-09T21:40:17.800157335+08:00" level=info msg="Star>
Sep 09 21:40:18 docker dockerd[2309]: time="2024-09-09T21:40:18.196566715+08:00" level=info msg="[gra>
Sep 09 21:40:18 docker dockerd[2309]: time="2024-09-09T21:40:18.208666863+08:00" level=info msg="Load>
Sep 09 21:40:19 docker dockerd[2309]: time="2024-09-09T21:40:19.587647943+08:00" level=info msg="Defa>
Sep 09 21:40:19 docker dockerd[2309]: time="2024-09-09T21:40:19.881267095+08:00" level=info msg="Load>
Sep 09 21:40:19 docker dockerd[2309]: time="2024-09-09T21:40:19.956577565+08:00" level=info msg="Dock>
Sep 09 21:40:19 docker dockerd[2309]: time="2024-09-09T21:40:19.957045036+08:00" level=info msg="Daem>
Sep 09 21:40:20 docker dockerd[2309]: time="2024-09-09T21:40:20.014584201+08:00" level=info msg="API >
Sep 09 21:40:20 docker systemd[1]: Started Docker Application Container Engine.

Docker 镜像

可将 Docker 镜像看着只读模板,通过它可以创建 Docker 容器。

例如某个镜像可能包含一个 Ubuntu 操作系统、一个 Apache HTTP Server 以及用户开发的 Web 应用。

镜像有多种生成方法:

  1. 可以从无到有开始创建镜像
  2. 也可以下载并使用别人创建好的现成的镜像
  3. 还可以在现有镜像上创建新的镜像

我们可以将镜像的内容和创建步骤描述在一个文本文件中,这个文件被称作 Dockerfile,通过执行 docker build <docker-file> 命令可以构建出 Docker 镜像,后面我们会讨论。

Docker 容器

Docker 容器就是 Docker 镜像的运行实例。

用户可以通过 CLI(docker)或是 API 启动、停止、移动或删除容器。可以这么认为,对于应用软件,镜像是软件生命周期的构建和打包阶段,而容器则是启动和运行阶段。

Registry

Registry 是存放 Docker 镜像的仓库,Registry 分私有和公有两种。

Docker Hub(https://hub.docker.com/) 是默认的 Registry,由 Docker 公司维护,上面有数以万计的镜像,用户可以自由下载和使用。

出于对速度或安全的考虑,用户也可以创建自己的私有 Registry。后面我们会学习如何搭建私有 Registry。

docker pull 命令可以从 Registry 下载镜像。

docker run 命令则是先下载镜像(如果本地没有),然后再启动容器。

下一节我们通过一个例子来看各个组件是如何协调工作的。


008 Docker组件如何协作?

还记得我们运行的第一个容器吗?现在通过它来体会一下 Docker 各个组件是如何协作的。

容器启动过程如下:

  1. Docker 客户端执行 docker run 命令。
  2. Docker daemon 发现本地没有 httpd 镜像。
  3. daemon 从 Docker Hub 下载镜像。
  4. 下载完成,镜像 httpd 被保存到本地。
  5. Docker daemon 启动容器。

docker images 可以查看到 httpd 已经下载到本地。

shell 复制代码
[root@docker ~]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
httpd        latest    9cb0a2315602   7 weeks ago   148MB

docker ps 或者 docker container ls 显示容器正在运行。

小结

Docker 借鉴了集装箱的概念。标准集装箱将货物运往世界各地,Docker 将这个模型运用到自己的设计哲学中,唯一不同的是:集装箱运输货物,而 Docker 运输软件。

每个容器都有一个软件镜像,相当于集装箱中的货物。容器可以被创建、启动、关闭和销毁。和集装箱一样,Docker 在执行这些操作时,并不关心容器里到底装的什么,它不管里面是 Web Server,还是 Database。

用户不需要关心容器最终会在哪里运行,因为哪里都可以运行。

开发人员可以在笔记本上构建镜像并上传到 Registry,然后 测试人员将镜像下载到物理或虚拟机做测试,最终容器会部署到生产环境。

使用 Docker 以及容器技术,我们可以快速构建一个应用服务器、一个消息中间件、一个数据库、一个持续集成环境。因为 Docker Hub 上有我们能想到的几乎所有的镜像。

不知大家是否意识到,潘多拉盒子已经被打开。容器不但降低了我们学习新技术的门槛,更提高了效率。

如果你是一个运维人员,想研究负载均衡软件 HAProxy,只需要执行docker run haproxy,无需繁琐的手工安装和配置既可以直接进入实战。

如果你是一个开发人员,想学习怎么用 django 开发 Python Web 应用,执行 docker run django,在容器里随便折腾吧,不用担心会搞乱 Host 的环境。

不夸张的说:容器大大提升了 IT 人员的幸福指数。


相关推荐
2601_9620739725 分钟前
大数据-258 离线数仓 - Griffin架构 配置安装 Livy 架构设计 解压配置 Hadoop Hive
大数据·hadoop·架构
天天喝旺仔36 分钟前
Docker 镜像瘦身实战:多阶段构建把体积缩小 90%
运维·后端·ci/cd·docker·云原生·容器·性能优化
NJCloud1 小时前
Docker 私有仓库部署:Registry、加密传输与认证鉴权
运维·网络·docker·云原生·容器
w200512241 小时前
K8S控制器管理
linux·云原生·容器·kubernetes
weixin199701080161 小时前
二手ERP对接闲鱼API:聚石塔强制入塔后的架构重构实录(正文骨架)
重构·架构
2601_962069771 小时前
【软件架构】软件的十二种架构简介
架构
风123456789~1 小时前
【架构专栏】2.6 计算机语言
架构
2601_962203511 小时前
构建高可用和高防御力的云服务架构第五部分:PolarDB(55)
架构
charles_he1 小时前
Agent 写操作超时后,最危险的动作是“再试一次”
人工智能·架构·agent