锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

Docker 入门教程

时间:2022-09-07 00:30:00 da4y变送器智能温度变送器ad180fdsh8c15连接器

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,包括文件系统、网络互联、镜像管理在内的进一步包装,极大地简化了容器管理。.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 系统交互图如下:

图片来源:Docker 0.9: introducing execution drivers and libcontainer

命名空间「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 上的一个 ocker 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

  • Docker Getting Start: Related Knowledge
  • Docker 介绍以及其相关术语、底层原理和技术

资源配额「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/中。

[root@localhost ~]# docker history nginx        <<== 查看镜像有哪些分层
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
62f816a209e6        37 hours ago        /bin/sh -c #(nop)  CMD ["nginx" "-g" "daemon…   0B
           37 hours ago        /bin/sh -c #(nop)  STOPSIGNAL [SIGTERM]         0B
           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-shares CPU共享(相对权重)

示例 :( 内存 限额、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
                            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-db MySQL数据库
harbor-jobservice 负责镜像复制
harbor-log 记录操作日志
harbor-ui web管理页面和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
  • 访问 portainer。访问网址:http://127.0.0.1:9000

十、构建容器监控系统

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
锐单商城拥有海量元器件数据手册IC替代型号,打造电子元器件IC百科大全!

相关文章