Docker 入门教程

本文详细介绍了Docker的基础知识,包括Docker的体系结构、内部组件如命名空间和资源配额cgroups,以及Docker的安装过程。文章还深入探讨了容器与虚拟机的区别,并提供了Linux环境下Docker的安装步骤。此外,还讲解了镜像管理和容器管理,如镜像创建、容器资源限制以及数据管理。最后,提到了企业级镜像仓库Harbor的部署和使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

From:http://www.manongjc.com/article/18866.html

docker 官网文档:https://docs.docker.com/

Docker 入门教程安装手册http://www.docker.org.cn/book

入门教程

一、Docker 介绍

1.1 什么是 Docker

  • ​Docker 是一个开源的应用容器引擎,使用 Go 语言开发,基于 Linux 内核的 cgroup、namespace、Union FS 等技术,对应用进程进行封装隔离,并且独立于宿主机与其他进程,这种运行时封装的状态 称为容器
  • Docker 早期版本实现是基于 LXC,并进一步对其封装,包括文件系统、网络互联、镜像管理等方面,极大简化了容器管理。从0.7版本以后开始去除 LXC,转为自己研发的libcontainer,从1.11版本开始,进一步为使用 runC containerd

​Docker 理念:将 "应用" 及 "依赖包" 打包到一个可移植的容器中,可发布到任意 Linux 发行版 Docker 引擎上。使用沙箱机制运行程序,程序之间相互隔离。

1.2 Docker 体系结构​

  • Containerd:是一个简单的守护进程,使用 runC 管理 容器。向 Docker Engine 提供接口。
  • Shim:只负责管理一个容器。
  • runC:是一个轻量级的工具,只用来运行容器。

  • Docker Client:客户端
  • Docker Daemon:守护进程
  • Docker Images:镜像
  • Docker Container:容器
  • Docker Registry:镜像仓库

Docker 简介

Docker 两个主要部件:

  • Docker: 开源的容器虚拟化平台
  • Docker Hub: 用于分享、管理 Docker 容器的 Docker SaaS 平台 -- Docker Hub

Docker 使用 "客户端 --- 服务器 (C/S)" 架构模式。Docker 客户端 会与 Docker 守护进程 进行通信。Docker 守护进程 会处理复杂繁重的任务,例如:建立、运行、发布你的 Docker 容器。Docker 客户端守护进程 可以运行在同一个系统上,当然你也可以使用 Docker 客户端 去连接一个 远程的 Docker 守护进程Docker 客户端守护进程 之间通过 socket 或者 RESTful API 进行通信。

​Docker 守护进程

如上图所示,Docker 守护进程运行在一台主机上。用户并不直接和守护进程进行交互,而是通过 Docker 客户端间接和其通信。

Docker 客户端

Docker 客户端,实际上是 docker 的二进制程序,是主要的用户与 Docker 交互方式。它接收用户指令并且与背后的 Docker 守护进程通信,如此来回往复。

Docker 内部( 镜像、仓库、容器 )

要理解 Docker 内部构建,需要理解以下三种部件:

  • Docker 镜像 --- Docker images : Docker 镜像是 Docker 容器运行时的只读模板,每一个镜像由一系列的层 (layers) 组成。Docker 使用 UnionFS 来将这些层联合到单独的镜像中。UnionFS 允许独立文件系统中的文件和文件夹(称之为分支)被透明覆盖,形成一个单独连贯的文件系统。正因为有了这些层的存在,Docker 是如此的轻量。当你改变了一个 Docker 镜像,比如升级到某个程序到新的版本,一个新的层会被创建。因此,不用替换整个原先的镜像或者重新建立(在使用虚拟机的时候你可能会这么做),只是一个新 的层被添加或升级了。现在你不用重新发布整个镜像,只需要升级,层使得分发 Docker 镜像变得简单和快速。
  • Docker 仓库 --- Docker registeries : Docker 仓库用来保存镜像,可以理解为代码控制中的代码仓库。同样的,Docker 仓库也有公有和私有的概念。公有的 Docker 仓库名字是 Docker Hub。Docker Hub 提供了庞大的镜像集合供使用。这些镜像可以是自己创建,或者在别人的镜像基础上创建。Docker 仓库是 Docker 的分发部分。
  • Docker 容器 --- Docker containers : Docker 容器和文件夹很类似,一个Docker容器包含了所有的某个应用运行所需要的环境。每一个 Docker 容器都是从 Docker 镜像创建的。Docker 容器可以运行、开始、停止、移动和删除。每一个 Docker 容器都是独立和安全的应用平台,Docker 容器是 Docker 的运行部分。

libcontainer

Docker 从 0.9 版本开始使用 libcontainer 替代 lxc,libcontainer 和 Linux 系统的交互图如下:

命名空间「Namespaces」

pid namespace

不同用户的进程就是通过 pid namespace 隔离开的,且不同 namespace 中可以有相同 PID。具有以下特征:

  • 每个 namespace 中的 pid 是有自己的 pid=1 的进程(类似 /sbin/init 进程)
  • 每个 namespace 中的进程只能影响自己的同一个 namespace 或子 namespace 中的进程
  • 因为 /proc 包含正在运行的进程,因此在 container 中的 pseudo-filesystem 的 /proc 目录只能看到自己 namespace 中的进程
  • 因为 namespace 允许嵌套,父 namespace 可以影响子 namespace 的进程,所以子 namespace 的进程可以在父 namespace 中看到,但是具有不同的 pid

参考文档:Introduction to Linux namespaces – Part 3: PID

mnt namespace

类似 chroot,将一个进程放到一个特定的目录执行。mnt namespace 允许不同 namespace 的进程看到的文件结构不同,这样每个 namespace 中的进程所看到的文件目录就被隔离开了。同 chroot 不同,每个 namespace 中的 container 在 /proc/mounts 的信息只包含所在 namespace 的 mount point。

net namespace

网络隔离是通过 net namespace 实现的, 每个 net namespace 有独立的 network devices, IP addresses, IP routing tables, /proc/net 目录。这样每个 container 的网络就能隔离开来。 docker 默认采用 veth 的方式将 container 中的虚拟网卡同 host 上的一个 docker bridge 连接在一起。

参考文档:Introduction to Linux namespaces – Part 5: NET

uts namespace

UTS ("UNIX Time-sharing System") namespace 允许每个 container 拥有独立的 hostname 和 domain name, 使其在网络上可以被视作一个独立的节点而非 Host 上的一个进程。

参考文档:Introduction to Linux namespaces – Part 1: UTS

ipc namespace

container 中进程交互还是采用 Linux 常见的进程间交互方法 (interprocess communication - IPC), 包括常见的信号量、消息队列和共享内存。然而同 VM 不同,container 的进程间交互实际上还是 host 上具有相同 pid namespace 中的进程间交互,因此需要在IPC资源申请时加入 namespace 信息 - 每个 IPC 资源有一个唯一的 32bit ID。

参考文档:Introduction to Linux namespaces – Part 2: IPC

user namespace

每个 container 可以有不同的 user 和 group id, 也就是说可以以 container 内部的用户在 container 内部执行程序而非 Host 上的用户。

有了以上 6 种 namespace 从进程、网络、IPC、文件系统、UTS 和用户角度的隔离,一个 container 就可以对外展现出一个独立计算机的能力,并且不同 container 从 OS 层面实现了隔离。 然而不同 namespace 之间资源还是相互竞争的,仍然需要类似 ulimit 来管理每个 container 所能使用的资源 - cgroup。

Reference

资源配额「cgroups」

cgroups 实现了对资源的配额和度量。 cgroups 的使用非常简单,提供类似文件的接口,在 /cgroup 目录下新建一个文件夹即可新建一个 group,在此文件夹中新建 task 文件,并将 pid 写入该文件,即可实现对该进程的资源控制。具体的资源配置选项可以在该文件夹中新建子 subsystem ,{子系统前缀}.{资源项} 是典型的配置方法, 如 memory.usageinbytes 就定义了该 group 在 subsystem memory 中的一个内存限制选项。 另外,cgroups 中的 subsystem 可以随意组合,一个 subsystem 可以在不同的 group 中,也可以一个 group 包含多个 subsystem - 也就是说一个 subsystem。

  • memory : 内存相关的限制
  • cpu : 在 cgroup 中,并不能像硬件虚拟化方案一样能够定义 CPU 能力,但是能够定义 CPU 轮转的优先级,因此具有较高 CPU 优先级的进程会更可能得到 CPU 运算。 通过将参数写入 cpu.shares ,即可定义改 cgroup 的 CPU 优先级 - 这里是一个相对权重,而非绝对值
  • blkio : block IO 相关的统计和限制,byte/operation 统计和限制 (IOPS 等),读写速度限制等,但是这里主要统计的都是同步 IO
  • devices : 设备权限限制

参考文档:how to use cgroup

1.3 Docker 内部组件

  1. Namespaces:命名空间,Linux 内核提供的一种对进程资源隔离的机制,例如 进程、网络、挂载点等资源。
  2. CGroup:控制组,Linux 内核提供的一种限制进程资源的机制;例如 CPU、内存 等资源。
  3. UnionFS:联合文件系统,支持将不同位置的目录挂载到同一虚拟文件系统,形成一种分层的模型。

1.4 什么是 容器 ?

  • ​对软件和其依赖的标准化打包
  • 应用之间相互隔离
  • 共享同一个OS Kernel
  • 可以运行在很多主流操作系统上

1.5 容器虚拟机 的区别

KVM 为例与 Docker 对比

  1. 启动时间:Docker 妙级启动,KVM 分钟级启动。
  2. 轻量级:容器镜像通常以M为单位,虚拟机以G为单位。容器资源占用小,要比虚拟机部署更快捷。
  3. 性能:容器共享宿主机内核,系统级虚拟化,占用资源少,没有 Hypervisor 层开销,容器性能基本接近物理机;虚拟机需要 Hypervisior 层支持,虚拟化一些设备,具备完整的GuestOS,虚拟化开销大,因而降低性能,没有容器性能好。
  4. 安全性:由于共享宿主机内核,只是进程级隔离,因此隔离性和稳定性不如虚拟机,容器具有一定权限访问宿主机内核,存在一定安全隐患。
  5. 使用要求:KVM 基于硬件的完全虚拟化、需要赢家 CPU 虚拟化技术支持;容器共享所主机内核,可运行在主流的 Linux 发行版,不用考虑 CPU 是否支持虚拟化技术。

1.6 虚拟化 + 容器

二、Docker 安装

Docker 官网:https://wwww.docker.com

docker 的相关安装方法可以参考 官档https://docs.docker.com/install/

获取当前 docker 版本

$ sudo docker version
Client version: 1.3.2
Client API version: 1.15
Go version (client): go1.3.3
Git commit (client): 39fa2fa/1.3.2
OS/Arch (client): linux/amd64
Server version: 1.3.2
Server API version: 1.15
Go version (server): go1.3.3
Git commit (server): 39fa2fa/1.3.2

2.2 Docker 版本

  • 社区版(Community Edition,CE)
  • 企业版(Enterprise Edition,EE)

2.3 支持的平台

  • Linux(CentOS、Debian、Fedora、Oracle Linux、RHEL、SUSE 和 Ubuntu )
  • Mac
  • Windows

2.4 Linux 安装 Docker

2.4.1 Docker 文档

https://docs.docker.com
https://docs.docker.com/install/linux/docker-ce/centos/#set-up-the-repository

2.4.2 Docker的 安装启动运行进入查看命令

2.4.2.1 关闭防火墙

systemctl stop firewalld
  systemctl disable firewalld

2.4.2.2 关闭 selinux

vi /etc/selinux/config
SELINUX=disabled    #设置为disabled
reboot  #重启服务器
# 查看selinux状态
[root@localhost ~]# getenforce
Disabled

2.4.2.3 安装所需的包

yum install -y yum-utils   device-mapper-persistent-data   lvm2

2.4.2.4 配置 yum 源

yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

2.4.2.5 安装 docker-ce

yum install docker-ce -y

2.4.2.6 启动

systemctl start docker
# 加入开机启动
systemctl enable docker

2.4.2.7 运行 hello-world

docker run hello-world

2.4.2.8查看 docker 版本

[root@localhost ~]# docker info

输出省略。。。

[root@localhost ~]# docker version

输出省略。。。

2.4.2.9 查看运行了哪些 docker

[root@localhost ~]# docker run -it nginx   // -it前台运行、再打开一个终端用于查看
[root@localhost ~]# docker ps              // 列出正在运行的 容器
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
336509fd6799        nginx               "nginx -g 'daemon of…"   8 minutes ago       Up 8 minutes        80/tcp              epic_ride

docker ps --help  ( docker ps  不加参数 表示列出正在运行的容器 )

docker ps --help

Usage:  docker ps [OPTIONS]
List containers

Options:
  -a, --all             Show all containers (default shows just running)
  -f, --filter filter   Filter output based on conditions provided
      --format string   Pretty-print containers using a Go template
  -n, --last int        Show n last created containers (includes all
                        states) (default -1)
  -l, --latest          Show the latest created container (includes all
                        states)
      --no-trunc        Don't truncate output
  -q, --quiet           Only display container IDs
  -s, --size            Display total file sizes

2.4.2.10 查看 容器信息

[root@localhost ~]# docker inspect 336509fd6799    <<==容器的id,用docker ps查看得到 

输出省略。。。

[root@localhost ~]# curl -I 172.17.0.2
HTTP/1.1 200 OK
Server: nginx/1.15.6
Date: Thu, 08 Nov 2018 12:43:20 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 06 Nov 2018 13:32:09 GMT
Connection: keep-alive
ETag: "5be197d9-264"
Accept-Ranges: bytes

2.4.2.11 进入容器中

[root@localhost ~]# docker exec -it 336509fd6799 bash
root@336509fd6799:/# ls
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@336509fd6799:/# exit
exit

进入 docker 中的 4 种方式 ( docker execdocker run )

方式 1: 使用 docker exec 命令进入docker容器( 最常用的方法,没有之一 )

  docker 在 1.3.x 版本之后提供了一个新命令 exec 用户进入容器。  

  该命令是本篇博客中的主角,是个大boss。下面的三种方式都是为了衬托它的存在。。。

  该方法是最常用的方法,没有之一!!!!!

$ docker ps
$ docker exec -it mynginx /bin/bash

  对,你没看错,这个命令就是这么简单。

docker run docker exec 的差异( https://www.cnblogs.com/miracle-luna/p/11111852.html )

  • docker run :根据镜像 创建一个容器 并运行一个命令,操作的对象是 镜像
  • docker exec :运行的容器中 执行命令,操作的对象是 容器

方式 2: 使用 docker attach 命令进入 docker

Docker 提供了 attach 命令来进入 Docker 容器

docker run -itd nginx-name mynginx
docker attach mynginx
# 或者
docker attach mynginx

优缺点:
  当多个窗口使用该命令进入该容器时,所有窗口都会显示同步。如果一个窗口阻塞了,其他窗口无法再进行操作;。
  因此 docker attach 命令不太适合于生产环境。且该命令有点古老,不太建议使用
PS:
  最近在家里的 windows 系统中使用 docker attach mynginx 命令进入 docker 容器卡死窗口。可能该命令太古老了,高版本用有点问题。

方式 3: 使用 ssh 进入 docker 容器

docker 就是一个隔离的盒子,可以看做是最原始初始化的盒子,可以将它当做一个 mini 型 的 linux 虚拟机,我们在该盒子中安装我们需要的服务(例如:nginx、mysql、redis等),打包之后就形成了目前最为流行的 docker 应用容器。既然是一个linux 虚拟主机,那么我们就可以在该主机上面安装一个 ssh server 就可以通过 ssh 协议来连接该容器了。

不过这种方式也基本没什么人用,出力不讨好。哈哈,那是因为后面有一种既安全又便捷的命令用啦。

可以去看一下这个老外写的原因:为什么不需要在 Docker 容器中运行 sshd:https://www.oschina.net/translate/why-you-dont-need-to-run-sshd-in-docker?cmp

方式 4: 使用 nsenter 进入 docker 容器

  对于 nsenter 网上有比较多且详细的介绍,这里我就说一下我自己理解。
  个人理解 nsenter:通过容器在宿主机中的 pid 进行通讯
  因此:nsenter 需要在宿主机安装,而 非 容器 或者 镜像

# 安装nsenter
$ wget https://www.kernel.org/pub/linux/utils/util-linux/v2.24/util-linux-2.24.tar.gz  
$ tar -xzvf util-linux-2.24.tar.gz  
$ cd util-linux-2.24/  
$ ./configure --without-ncurses  
$ make nsenter  
$ sudo cp nsenter /usr/local/bin  

$ nsenter --help

# nsenter可以访问另一个进程名称空间。因此我们需要获取容器的PID
sudo docker inspect -f {{.State.Pid}} 44fc0f0582d9  // 假设进程号为 4426
$ sudo nsenter --target 4426 --mount --uts --ipc --net --pid  
# --target 4426 目标pid

三、镜像管理

3.1 镜像是什么

  • 一个分层存储的文件
  • 一个软件的环境
  • 一个镜像可以创建N个容器
  • 一种标准化的交付
  • 一个不包含Linux内核而又精简的Linux操作系统

镜像不是一个单一的文件,而是有多层构成。我们可以通过docker history 查看镜像中各层内容及大小,每层对应着Dockerfile中的一条指令。Docker镜像默认存储在/var/lib/docker/<storage-driver>中。

[root@localhost ~]# docker history nginx        <<== 查看镜像有哪些分层
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
62f816a209e6        37 hours ago        /bin/sh -c #(nop)  CMD ["nginx" "-g" "daemon…   0B
<missing>           37 hours ago        /bin/sh -c #(nop)  STOPSIGNAL [SIGTERM]         0B
<missing>           37 hours ago        /bin/sh -c #(nop)  EXPOSE 80/tcp                


[root@localhost ~]# cd /var/lib/docker/
[root@localhost docker]# ls
builder  buildkit  containerd  containers  image  network  overlay2  plugins  runtimes  swarm  tmp  trust  volumes
[root@localhost docker]# cd overlay2/
[root@localhost overlay2]# ls
240731a3ae18beffce7a5053fb4b45c4a93c52c14b2b18e25751bd5ef5bce0b5
31cc93e4ef8b9da5b5d98bc9a68cfdd8c1ba2a31bf65bcb21754defd68d85c5d
31cc93e4ef8b9da5b5d98bc9a68cfdd8c1ba2a31bf65bcb21754defd68d85c5d-init
613cf356b8ebdacffabca1e2f03c02102a19d13df25caef091c10858ec058731
802c4abe1551fbbba1e4445b149852e2b0a8eb969adc2a45955d60ea88cdd370
82d2821d41013463c69c23a8c1e58a96ab84ae9c6399a181d0b37f0459c8007b
b5044ef06828dd2656c0d59f03cd854917033fe8ebd2e26bc3332b359cfcc148
b5044ef06828dd2656c0d59f03cd854917033fe8ebd2e26bc3332b359cfcc148-init
backingFsBlockDev
l

3.1.1 镜像从那里来?

Docker Hub是由Docker公司负责维护的公共注册中心,包含大量的容器镜像,Docker工具默认从这个公共镜像库下载镜像。地址:https://hub.docker.com/explore

3.1.2 配置镜像加速器

https://www.daocloud.io/mirror
curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://f1361db2.m.daocloud.io
systemctl restart docker

3.2 镜像与容器联系

​如图,容器其实是在镜像的最上面加了一层读写层,在运行容器里文件改动时,会先从镜像里面要写的文件复制到容器自己的文件系统中(读写层)。

如果容器删除了,最上面的读写层也就被删除了,改动也就丢失了。所以无论多少个容器共享一个镜像,所做的写操作都是从镜像的文件系统中复制过来操作的,并不会修改镜像的源文件,这种方式提高磁盘利用率。

若想持久化这些改动,可以通过docker commit将容器保存成一新的镜像。

root@localhost ~]# docker run -itd nginx
5ba9e0be87ade5e68481bface386c8ef592bb80bbe7bf28cf1572e832c8ce355

[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
5ba9e0be87ad        nginx               "nginx -g 'daemon of…"   51 seconds ago      Up 50 seconds       80/tcp              sharp_mayer
[root@localhost ~]# docker exec -it 5ba9e0be87ad bash
root@5ba9e0be87ad:/# ls
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@5ba9e0be87ad:/# touch nginx.txt
root@5ba9e0be87ad:/# exit
exit
[root@localhost ~]# docker inspect 5ba9e0be87ad
....
# 存储驱动
GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/44cfba513bee96fa98dd85ef9cbf8a88f8286c90291b498a615be6f590bda66a-init/diff:/var/lib/docker/overlay2/240731a3ae18beffce7a5053fb4b45c4a93c52c14b2b18e25751bd5ef5bce0b5/diff:/var/lib/docker/overlay2/613cf356b8ebdacffabca1e2f03c02102a19d13df25caef091c10858ec058731/diff:/var/lib/docker/overlay2/82d2821d41013463c69c23a8c1e58a96ab84ae9c6399a181d0b37f0459c8007b/diff",
                "MergedDir": "/var/lib/docker/overlay2/44cfba513bee96fa98dd85ef9cbf8a88f8286c90291b498a615be6f590bda66a/merged",
                "UpperDir": "/var/lib/docker/overlay2/44cfba513bee96fa98dd85ef9cbf8a88f8286c90291b498a615be6f590bda66a/diff",
                "WorkDir": "/var/lib/docker/overlay2/44cfba513bee96fa98dd85ef9cbf8a88f8286c90291b498a615be6f590bda66a/work"
            },
            "Name": "overlay2"
        },
       ...


[root@localhost ~]# cd /var/lib/docker/overlay2/44cfba513bee96fa98dd85ef9cbf8a88f8286c90291b498a615be6f590bda66a
[root@localhost 44cfba513bee96fa98dd85ef9cbf8a88f8286c90291b498a615be6f590bda66a]# ls
diff  link  lower  merged  work
[root@localhost 44cfba513bee96fa98dd85ef9cbf8a88f8286c90291b498a615be6f590bda66a]# ls diff/         # 与惊喜差异
nginx.txt  root  run  var
[root@localhost 44cfba513bee96fa98dd85ef9cbf8a88f8286c90291b498a615be6f590bda66a]# ls merged/   <<==Nginx工作的数据驱动存储
bin  boot  dev  etc  home  lib  lib64  media  mnt  nginx.txt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@localhost 44cfba513bee96fa98dd85ef9cbf8a88f8286c90291b498a615be6f590bda66a]# ls work/
work

3.3 管理镜像常用命令

docker image --help

指令描述
ls列出镜像
build构建镜像来自Dockerfile
history查看镜像历史
inspect显示一个或多个镜像详细信息
pull推送一个镜像到镜像仓库
rm移除一个或多个镜像
prune移除未使用的镜像。没有被标记或被任何容器引用的。
tag创建一个引用源镜像标记目标镜像
export导出容器文件系统到tar归档文件
import导入容器文件系统tar归档创建镜像
save保存一个或多个镜像到tar归档文件
load

加载镜像来自tar归档或标准输入

四、容器管理

4.1 创建容器常用选项

docker container run --help

选项描述
-i,-interactive交互式
-t,-tty分配一个伪终端
-d,-detach运行容器到后台
-e,-env设置环境变量
-p,-publish list发布容器端口到主机
-P,-publish-all发布容器所有EXPOSE端口到宿主机随机端口
-name string指定容器名称
-h,-hostname设置容器主机名
-ip string指定容器IP,只能用于自定义网络
-network连接容器到一个网络
-mount mount将文件系统附加到容器
-v,-volume list绑定挂载一个卷
-restart string容器退出时重启策略,默认no,可选值:[always|on-failure]

4.2 容器资源限制

选项描述
-m,-memory容器可以使用的最大内存量
-memory-swap允许交换磁盘的内存量
-memory-swappiness=<0-100>容器使用SWAP分区交换的百分比(0-100,默认为-1)
-oom-kill-disable禁用OOM Killer
-cpus可以使用的CPU数量
-cpuset-cpus限制容器使用特定的CPU核心,(0-3,0,1)
-cpu-sharesCPU共享(相对权重)

示例 :( 内存 限额、CPU 限额 )

4.2.1 内存 限额

允许容器最多使用500M内存和100M的swap,并禁用OOM Killer:
# 允许使用的swap=memory-swap - memory
# memory-swap='-1'时,无限制使用swap
# memory-swap 不设置时,默认swap的值时memory的2倍
# memory-swap的值等于memory值时,禁用swap
docker run -d --name Nginx01 --memory="500m" --memory-swap="600M" --oom-kill-disable nginx

4.2.2 CPU 限额

允许容器最多使用一个半的 CPU:

docker run -d --name nginx04 --cpus="1.5" nginx

允许容器最多使用 50% 的CPU:

docker run -d --name nginx05 --cpus='.5' nginx

4.3 管理容器常用命令

docker container --help

选项描述
ls列出容器
inspect查看一个或多个容器详细信息
commit创建一个新镜像来自一个容器
cp拷贝文件/文件夹到一个容器
logs获取一个容器日志
port列出或指定容器端口映射
top显示一个容器运行的进程
stats显示容器资源使用统计
stop/start停止/启动一个或多个容器
rm删除一个或多个容器

五、管理 应用程序 数据

5.1 将宿主机数据挂载到容器中的三种方式

​Docker提供三种方式数据从宿主机挂载到容器中:

  • Volumes:Docker管理宿主机文件系统的一部分(/var/lib/docker/volumes)。保存数据的最佳方式。
  • bind mounts:将宿主机上的任意位置的文件或者目录挂载到容器中。
  • tmpfs:挂载存储在主机系统的内存中,而不会写入主机的文件系统。如果不希望将数据持久化存储到任何位置,可以使用tmpfs,同时避免写入容器可写层提高性能。

5.2 Volume

  • 管理卷
docker volume create nginx-vol
docker volume ls
docker volume inspect nginx-vol
  • 用卷创建一个容器
# 新语法
docker run -d --name=nginx-test --mount src=nginx-vol,dst=/usr/share/nginx/html nginx
# 旧语法
docker run -d --name=nginx-test -v nginx-vol:/usr/share/nginx/html nginx
  • 清理
docker stop nginx-test
docker rm nginx-test
docker volume rm nginx-vol

注意:

1. 如果没有指定卷,自动创建。
2. 建议使用—mount,更通用。

https://docs.docker.com/engine/admin/volumes/volumes/#start-a-container-with-a-volume

5.3 Bind Mounts

  • 用卷创建一个容器
# 新语法
docker run -d --name=nginx-test --mount type=bind,src=/app/wwwroot,dst=/usr/share/nginx/html nginx
# 旧语法
docker run -d --name=nginx-test -v /app/wwwroot:/usr/share/nginx/html nginx
  • 验证绑定
docker inspect nginx-test
  • 清理
docker stop nginx-test
docker rm nginx-test

注意:

1.2 如果源文件/目录没有存在,不会自动创建,会抛出一个错误。

1.3 如果挂载目标在容器中非空目录,则该目录现有内容将被隐藏。

https://docs.docker.com/engine/admin/volumes/bind-mounts/#start-a-container-with-a-bind-mount

Volume特点

  • 多个运行容器之间共享数据。
  • 当容器停止或悲移除时,该卷依然存在。
  • 多个容器可以同时挂载相同的卷。
  • 当明确删除卷时,卷才会被删除。
  • 将容器的数据存储在远程主机或其他存储上
  • 将数据从一台Docker主机迁移到另一台时,先停止容器,然后备份卷的目录(/var/lib/docker/volumes)

Bind Mounts特点

  • 从主机共享配置文件到容器。默认情况下,挂载主机/etc/resolv.conf到每个容器,提供DNS解析。
  • 在Docker主机上的开发环境和容器之间共享源代码。例如,可以将Maven target目录挂载到容器中,每次在Docker主机上构建Maven项目时,容器都可以访问构建的项目包。
  • 当Docker主机的文件或目录结构保证与容器所需的绑定挂载一致时。

六、容器网络

6.1 Docker 四种网络模式 ( bridge、host、none、container )

  • bridge
            -net=bridge
            默认网络,Docker启动后创建一个docker0网桥,默认创建的容器也是添加到这个网桥中。
  • host
            -net=host
            容器不会获得一个独立的network namespace,而是与宿主机共用一个,
            这就意味着容器不会有自己的网卡信息,而是使用宿主机的。容器除了网络,其他都是隔离的。
  • none
            -net=none
            获取独立的network namespave,但不为容器进行任何网络配置,需要我们手动配置。
  • container
            -net=container:Name/ID
            与指定的容器使用同一个network namespace,具有同样的网络配置信息,两个容器除了网络,其他都还黑隔离的。
  • 自定义网络:与默认的bridge原理一样,但自定义网络具备内部DNS发现,可以通过容器名或者主机名容器之间网络通信。

6.2 容器网络 的 访问原理

​Linux IP信息包过滤原理:

Docker 主要通过 netfilter/iptables 实现网络通信。
iptables 由 netfilter 和 iptables 组成,netfilter 组件是 Linux 内核集成的信息包过滤系统,
它维护一个信息包过滤表,这个表用于控制信息包过滤处理的规则集,
而iptables只是一个在用户空间的工具,用于增删改查这个过滤表的规则。

filter(过滤)INPUT、OUTPUT、FORWARD
nat(地址转换)PREROUTING、POSTROUTING、OUTPUT
mangle(拆包、修改、封装)INPUT、OUTPUT、PREROUTING、 POSTROUTING、OUTPUT
raw(数据包状态跟踪)PREROUTING、OUTPUT

容器访问外部

# iptables -t nat -nL
Chain POSTROUTING (policy ACCEPT) target prot opt source MASQUERADE all -- 172.17.0.0/16
 destination
0.0.0.0/0

外部访问容器

Chain DOCKER (2 references) target prot opt source DNAT tcp -- 0.0.0.0/0
destination
0.0.0.0/0
tcp dpt:88 to:172.18.0.2:80

6.3 桥接宿主机网络与配置固定IP

  • 临时生效
# 网桥名称
br_name=br0
# 添加网桥
brctl addbr $br_name
# 给网桥设置IP
ip addr add 192.168.1.120/24 dev $br_name
# 删除已存在的eth0网卡配置
ip addr del 192.168.1.120/24 dev eth0
# 激活网卡
ip link set $br_name up
# 添加eth0到网桥
brctl addif $br_name eth0
# 添加路由
ip route add default via 192.168.1.1 dev br0

还需要在Docker启动时桥街这个网桥:
# vi /usr/lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -b=br0
# systemctl restart docker
  • 永久生效
# vi /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
TYPE=Ethernet
ONBOOT=yes
BRIDGE=br0

# vi /etc/sysconfig/network-scripts/ifcfg-br0
DEVICE=br0
TYPE=Bridge
ONBOOT=yes
BOOTPROTO=static
IPADDR=192.168.3.10
NETMASK=255.255.255.0
GATEWAY=192.168.3.1
DNS1=114.114.114.114
  • 配置固定IP
C_ID=$(docker run -itd --net=none ubuntu)
C_PID=$(docker inspect -f '{{.State.Pid}}' $C_ID)
# 创建network namespace目录并将容器的network namespace软连接到此目录,以便ip netns命令读取 mkdir -p /var/run/netns
ln -s /proc/$C_PID/ns/net /var/run/netns/$C_PID
# 添加虚拟网卡veth+容器PID,类型是veth pair,名称是vp+容器PID
ip link add veth$C_PID type veth peer name vp$C_PID
# 添加虚拟网卡到br0网桥
brctl addif br0 veth$C_PID
# 激活虚拟网卡
ip link set veth$C_PID up
# 设置容器网络信息
IP='192.168.0.123/24'
GW='192.168.0.1'
# 给进程配置一个network namespace
ip link set vp$C_PID netns $C_PID
# 在容器进程里面设置网卡信息
ip netns exec $C_PID ip link set dev vp$C_PID name eth0
ip netns exec $C_PID ip link set eth0 up
ip netns exec $C_PID ip addr add $IP dev eth0
ip netns exec $C_PID ip route add default via 192.168.1.1
  • pipework工具配置容器固定IP
git clone https://github.com/jpetazzo/pipework.git cp pipework/pipework /usr/local/bin/
docker run -itd --net=none --name test01 ubuntu pipework br0 test01 192.168.0.123/24@192.168.0.1

七、Dockerfile

7.1 Dockerfile 格式

FROM centos:latest
MAINTAINER huwl
RUN yum install gcc -y
COPY run.sh /usr/bin
EXPOSE 80
CMD ['run.sh]

7.2 Dockerfile 常用指令

指令描述
FROM构建新镜像是基于那个镜像
MAINTAINER镜像维护者姓名或邮箱地址
RUN构建镜像时运行的Shell命令
COPY拷贝文件或目录到镜像中
ENV设置环境变量
USER为RUN、CMD和ENTRPOTIN执行命令指定运行用户
EXPOSE声明容器运行的服务端口
HEALTHCHECK容器中服务健康检查
WORKDIR为RUN、CMD、ENTRYPOTIN、COPY和ADD设置工作目录
ENTRYPOIN运行容器时执行,如果有多个ENTRYPOIN指令,最后一个生效
CMD运行容器时执行,如果有多个CMD指令,最后一个生效

7.3 Build 构建镜像

Usage:docker build [OPTIONS] PATH | URL | - [flags]
Options:
-t, --tag list      # 镜像名称
-f,--file string    #指定Dockerfile文件位置


# docker build .
# docker bulid -t shykes/myapp .
# docker bulid -t shykes/myapp -f /path/Dockerfile /path
# docker bulid -t shykes/myapp http://www.example.com/Dockerfile

7.4 企业应用案例

7.4.1 构建Nginx基础镜像

  • Dockerfile
FROM centos:7
RUN yum install -y gcc gcc-c++ make openssl-devel pcre-devel dg-devel iproute net-tools telnet wget curl && yum clean all && rm -rf /var/cache/yum/*
RUN wget http://nginx.org/download/nginx-1.15.5.tar.gz && tar zxf nginx-1.15.5.tar.gz && cd nginx-1.15.5 && ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_stub_status_module && make && make install
ENV PATH $PATH:/usr/local/nginx/sbin
WORKDIR /usr/local/nginx
EXPOSE 80
CMD ["./sbin/nginx","-g","daemon off;"]
  • 构建镜像
docker build -t nginx:v1 -f Dockerfile .
# Successfully built 373a0bdefe50
# Successfully tagged nginx:v1

[root@localhost /]# docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               v1                  373a0bdefe50        56 seconds ago      335MB
<none>              <none>              d582c01a839f        4 minutes ago       200MB
nginx               latest              62f816a209e6        2 days ago          109MB
centos              7                   75835a67d134        4 weeks ago         200MB
hello-world         latest              4ab4c602aa5e        2 months ago        1.84kB
  • 启动测试
[root@localhost /]# docker run -d --name nginx100 -p 80:80 nginx:v1
a29daf4614116f7dba18461e871d1a45ec9b55f722a98bead791c12294b9f1d3
[root@localhost /]# docker ps -l
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
a29daf461411        nginx:v1            "./sbin/nginx -g 'da…"   6 seconds ago       Up 5 seconds        0.0.0.0:80->80/tcp   nginx100


[root@localhost /]# curl -I http://192.168.56.146/
HTTP/1.1 200 OK
Server: nginx/1.15.5
Date: Fri, 09 Nov 2018 12:34:03 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Fri, 09 Nov 2018 12:29:20 GMT
Connection: keep-alive
ETag: "5be57da0-264"
Accept-Ranges: bytes

7.4.2 构建 PHP 基础镜像

  • dockerfile
FROM centos:7
RUN yum install -y gcc gcc-c++ make gd-devel libxml2-devel libcurl-devel libjpeg-devel libpng-devel openssl-devel
ADD php-5.6.31.tar.gz /tmp/

RUN cd /tmp/php-5.6.31 && \
    ./configure --prefix=/usr/local/php \
    --with-config-file-path=/usr/local/php/etc \
    --with-mysql --with-mysqli \
    --with-openssl --with-zlib --with-curl --with-gd \
    --with-jpeg-dir --with-png-dir --with-iconv \
    --enable-fpm --enable-zip --enable-mbstring && \
    make -j 4 && \
    make install && \
    cp /usr/local/php/etc/php-fpm.conf.default /usr/local/php/etc/php-fpm.conf && \
    sed -i "s/127.0.0.1/0.0.0.0/" /usr/local/php/etc/php-fpm.conf && \
    sed -i "21a \daemonize = no" /usr/local/php/etc/php-fpm.conf
COPY php.ini /usr/local/php/etc

RUN rm -rf /tmp/php-5.6.31* && yum clean all

WORKDIR /usr/local/php
EXPOSE 9000
CMD ["./sbin/php-fpm", "-c", "/usr/local/php/etc/php-fpm.conf"]
  • 构建 php 镜像
docker build -t php:v1 -f dockerfile .
  • 启动测试
[root@localhost php]# docker run -d --name php01 php:v1
ed5276251a6bf5124efba4b314d29a2dbfd12ddc0e0c3371ea16184a07c12bbc
[root@localhost php]# docker ps -l
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
ed5276251a6b        php:v1              "./sbin/php-fpm -c /…"   5 seconds ago       Up 4 seconds        9000/tcp            php01
[root@localhost php]# docker exec -it php01 bash
[root@ed5276251a6b php]# ls
bin  etc  include  lib  php  sbin  var
[root@ed5276251a6b php]# sbin/php-fpm -v
PHP 5.6.31 (fpm-fcgi) (built: Nov 10 2018 01:10:28)
Copyright (c) 1997-2016 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies

7.4.3 构建 Tomcat 基础镜像并项目测试

  • dockerfile
FROM centos:7

ADD jdk-8u45-linux-x64.tar.gz /usr/local
ENV JAVA_HOME /usr/local/jdk1.8.0_45

ADD apache-tomcat-8.0.46.tar.gz /usr/local
COPY server.xml /usr/local/apache-tomcat-8.0.46/conf

RUN rm -f /usr/local/*.tar.gz

WORKDIR /usr/local/apache-tomcat-8.0.46
EXPOSE 8080
ENTRYPOINT ["./bin/catalina.sh", "run"]
  • 构建 Tomcat 镜像
docker build -t tomcat:v1 -f Dockerfile .
  • 启动测试
[root@localhost tomcat]# docker run -d --name tomcat01 -p 8080:8080 tomcat:v1
b9ba85bc64748c90ebe8df19e41c36490881cbcf174dab00d127ae6bf1141814
[root@localhost tomcat]# curl -I http://192.168.56.146:8080
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=UTF-8
Transfer-Encoding: chunked
Date: Sat, 10 Nov 2018 01:26:59 GMT

7.5.1 快速部署 LNMP 网站平台

  • 创建自定义网络:docker network create lnmp
  • 创建 MySQL 容器:docker run -d --name lnmp_mysql --net lnmp --mount src=mysql-vol,dst=/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -e MYSQL_DATABASE=wordpress mysql:5.7 --character-set-server=utf8
  • 创建 PHP 容器:docker run -d --name lnmp_php --net lnmp --mount src=wwwroot,dst=/wwwwroot php:v1
  • 创建 Nginx 容器:docker run -d --name lnmp_nginx --net lnmp -p 80:80 --mount type=bind,src=$(pwd)/nginx.conf,dst=/usr/local/nginx/conf/nginx.conf --mount src=wwwroot,dst=/wwwroot nginx:v1
  • 以 wordpress 博客为例:https://cn.wordpress.org/wordpress-4.9.4-zh_CN.tar.gz

八、企业级镜像仓库 Harbor

8.1 Harbor 介绍

​ Habor 是由 VMWare 公司开源的容器镜像仓库。事实上,Habor是在Docker Registry上进行了相应的企业级扩展,从而获得了更加广泛的应用,这些新的企业级特性包括:管理用户界面,基于角色的访问控制,AD/DALP集成以及审计日志等,足以满足基本企业需求。

官方地址:https://vmware.github.io/harbor/cn/

组件功能
harbor-adminserver配置管理中心
harbor-dbMySQL数据库
harbor-jobservice负责镜像复制
harbor-log记录操作日志
harbor-uiweb管理页面和API
Nginx前端代理,负责前端页面和镜像上传或下载转发
reids会话
registry镜像存储

8.2 Harbor 部署

Harbor 安装有3种方式:

  • 在线安装:从Docker Hub下载Harbor相关镜像,因此安装软件包非常小
  • 离线安装:安装包包含部署的相关镜像,因此安装包比较大
  • OVA安装程序:当用户具有vCenter环境时,使用此安装程序,在部署OVA后启动Harbor

离线安装下载地址:https://github.com/goharbor/harbor/releases

  • 部署
curl -L "https://github.com/docker/compose/releases/download/1.22.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose

tar xf harbor-offline-installer-v1.6.1.tgz
cd harbor
vim harbor.cfg
harbor_admin_password = Harbor12345

./prepare
./install.sh

[root@localhost harbor]# docker-compose ps
       Name                     Command                  State                                    Ports
-------------------------------------------------------------------------------------------------------------------------------------
harbor-adminserver   /harbor/start.sh                 Up (healthy)
harbor-db            /entrypoint.sh postgres          Up (healthy)   5432/tcp
harbor-jobservice    /harbor/start.sh                 Up
harbor-log           /bin/sh -c /usr/local/bin/ ...   Up (healthy)   127.0.0.1:1514->10514/tcp
harbor-ui            /harbor/start.sh                 Up (healthy)
nginx                nginx -g daemon off;             Up (healthy)   0.0.0.0:443->443/tcp, 0.0.0.0:4443->4443/tcp, 0.0.0.0:80->80/tcp
redis                docker-entrypoint.sh redis ...   Up             6379/tcp
registry             /entrypoint.sh /etc/regist ...   Up (healthy)   5000/tcp
  • 访问 http://192.168.56.146/harbor/sign-in

8.3 Harbor 基础使用

  • 默认上传镜像连接使用 https,添加 http 受信任
[root@localhost harbor]# cat /etc/docker/daemon.json
{
"registry-mirrors": ["http://f1361db2.m.daocloud.io"],
"insecure-registries": ["192.168.56.146"]       #<<= 加入harbor的地址

}
  • 重启 docker
systemctl restart docker

在 Harbor web 管理——“系统管理”——“用户管理”——新建用户,在——“项目”——“library仓库” ——“成员” 把之前添加的用户进来并赋予权限

  • 登录仓库上传镜像
docker tag nginx:v1 192.168.56.146/library/nginx:v1
docker login harbor地址
docker push 192.168.56.146/library/nginx:v1

九、图形化界面管理

9.1 Portainer

官网:https://portainer.io

安装:https://documentation.portainer.io/v2.0/deploy/ceinstalldocker/

​Portainer 是一个开源、轻量级 Docker 管理用户界面,基于 Docker API,可管理 Docker主机Swarm集群,支持最新版 Docker Swarm 模块

  • 创建卷:docker volume create portainer_data
  • 创建 Portainer 容器:docker run -d -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer

十、构建容器监控系统

10.1 cAdvisor + InfluxDB + Grafna

  • 创建 monitordocker network create monitor
  • Influxdbdocker run -d --name influxdb --net monitor -p 8083:8083 -p 8086:8086 tutum/influxdb
  • cAdvisordocker run -d --name=cadvisor --net monitor -p 8081:8080 --mount type=bind,src=/,dst=/rootfs,ro --mount type=bind,src=/var/run,dst=/var/run --mount type=bind,src=/sys,dst=/sys,ro --mount type=bind,src=/var/lib/docker/,dst=/var/lib/docker,ro google/cadvisor -storage_driver=influxdb -storage_driver_db=cadvisor -storage_driver_host=influxdb:8086
  • Grafanadocker run -d --name grafana --net monitor -p 3000:3000 grafana/grafana
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值