学习目标

  • 能够说出docker容器和虚拟机的主要区别

  • 能够说出docker用到的内核技术

  • 能够安装docker

  • 掌握镜像的常见操作

  • 掌握镜像仓库的搭建与使用

  • 掌握常见的容器操作命令

  • 能够查找docker存储驱动

  • 能够说出写时复制技术的特点

  • 能够说出overlay2联合文件系统的特点

  • 能够使用docker跑httpd等基础应用

  • 能够使用dockerfile构建容器镜像

  • 能够通过link连接容器

  • 能够说出docker本地网络的 4 种类型

  • 能够通过flannel网络实现容器互联

PAAS介绍

做云的优势: 提高资源利用率,将资源打包做成服务给用户使用,资源提供商极少需要与用户交互打交道。

CaaS 容器即服务就是PAAS的一种实现

由于hypervisor虚拟化技术仍然存在一些性能和资源使用效率方面的问题,因此出现了一种称为容器技术(Container)的新型虚拟化技术来帮助解决这些问题。

容器: 是PAAS的一种实现,相对于虚拟机来说有更好的性能,更高的资源利用率。

大型机-小型机-PC服务器-虚拟化-云计算-容器

一、认识容器技术

在生活中,瓶子,罐子,盆,试管,缸等都是用来装东西的容器。

在集装箱没有被使用以前,海上运输货物效率不高(货物大小与形状不一)。有了集装箱后,货物可以统一规格来存放与运输了,极大地提高了效率。

在IT技术中:

虚拟化技术可以在宿主机上安装多个不同的操作系统,运行多套不同的应用。但可能就是为了运行一个nginx,却还要在虚拟机里运行一个完整的操 作系统,内核和其它无关程序,这种做法资源利用不高。

所以我们希望更多的关注应用程序本身,而不再分精力去关注操作系统与无关程序,操作系统内核直接与宿主机共享

linux容器技术是一种 轻量级 的虚拟化技术。主要特点有:

  1. 轻量:只打包了需要的bins/libs(也就是命令和库文件)。与宿主机共享操作系统,直接使用宿主机的内核.

  2. 部署快: 容器的镜像相对虚拟机的镜像小。部署速度非常快,秒级部署

  3. 移植性好: Build once,Run anywhere(一次构建,随处部署运行)。
    build,ship,run

  4. 资源利用率更高: 相对于虚拟机,不需要安装操作系统,所以几乎没有额外的CPU,内存消耗


二、docker介绍

docker就是目前最火热的能实现容器技术的软件,使用go(golang)语言开发。

参考:https://www.docker.com/

Docker版本

2017 之前版本

1.7 ,1.8,1.9,1.10,1.11,1.12, 1.13

2017 年的 3 月 1 号之后 ,Docker的版本命名开始发生变化,同时将CE版本和EE版本进行分开。

Docker社区版(CE):为了开发人员或小团队创建基于容器的应用,与团队成员分享和自动化的开发管道。docker-ce提供了简单的安装和快速的安装,以便可以立即开始开发。docker-ce集成和优化,基础设施。

  • 17-03-ce

  • 17-06-ce

  • 18-03-ce

  • 18-06-ce

  • 18-09-ce

Docker企业版(EE):专为企业的发展和IT团队建立。docker-ee为企业提供最安全的容器平台,以应用为中心的平台。

docker用到的内核技术

docker容器本质上是宿主机的进程. 可以把docker容器内部跑的进程看作是宿主机的线程。

Docker通过namespace实现了资源隔离

通过cgroups实现了资源限制

NameSpace

Linux内核实现namespace的一个主要目的就是实现轻量级虚拟化(容器)服务。在同一个namespace下的进程可以感知彼此的变化,而对外界的进程一无所知。

Linux 在很早的版本中就实现了部分的 namespace,比如内核 2.4 就实现了mount namespace。

大多数的namespace支持是在内核 2.6 中完成的,比如 IPC、Network、PID、和 UTS。还有个别的namespace 比较特殊,比如User,从内核 2.6就开始实现了,但在内核 3.8 中才宣布完成。

同时,随着 Linux 自身的发展以及容器技术持续发展带来的需求,也会有新的 namespace 被支持,比如在内核 4.6 中就添加了Cgroup namespace。

inux内核提拱了 6 种namespace隔离的系统调用

namespace 系统调用参数 隔离内容
UTS CLONE_NEWUTS 主机名或域名
IPC CLONE_NEWIPC 信号量、消息队列和共享内存
PID CLONE_NEWPID 进程编号
net CLONE_NEWNET 网络设备接口,IP路由表、防火墙规则等
mount CLONE_NEWNS 挂载点(文件系统)
user CLONE_NEWUSER 用户和用户组

UTS: 每个NameSpace都拥有独立的主机名或域名,可以把每个NameSpace认为一个独立主机。

IPC: 每个容器依旧使用linux内核中进程交互的方法,实现进程间通信

PID: 每个容器都拥有独立的进程树,而容器是物理机中的一个进程,所以容器中的进程是物理机的线程

Net: 每个容器的网络是隔离

Mount: 每个容器的文件系统是独立的

User: 每个容器的用户和组ID是隔离,每个容器都拥有root用户

小结: 应用程序运行在一个隔离的空间(namespace)内, 每个隔离的空间都拥有独立的UTS,IPC,PID,Net,Mount,User.

Control Group

控制组(CGroups)是Linux内核的一个特性, 主要用来对共享资源进行隔离、限制、审计等 。

只有能控制分配到容器的资源,才能避免多个容器同时运行时对宿主机系统的资源竞争。

控制组可以提供对容器的内存、CPU、磁盘IO等资源进行限制和计费管理。

案例可参考优化课程文档

LXC与docker区别

LXC为Linux Container的简写。可以提供轻量级的虚拟化.

Docker的底层就是使用了LXC来实现的. docker以LXC为基础,实现了更多更强的功能。

前面内容小结:

  • 容器属于typeIII虚拟化,属于Paas

  • 容器是一种轻量级,进程级的虚拟机

  • 相比于虚拟机的优势

    • 不需要安装OS,和宿主机共享

    • 镜像存储空间小

    • 启动速度快(容器为秒级,虚拟机一般需要 10 秒左右)

    • 移植性更好,更轻便

    • 性能更好

  • docker是一个实现容器的软件,底层使用LXC

  • docker主要使用namespace命名空间技术实现资源隔离,使用cgroup实现资源限制

三、docker环境准备

建议直接在宿主机上跑docker(当然也可以在虚拟机里跑docker)

不能直接在windows上跑docker(因为namespace,cgroup是linux内核的特性,windows没有,所以需要在windows跑linux虚拟机,再跑docker)

  1. 要求能访问公网

  2. 关闭防火墙,selinux

docker软件安装

docker-ce的yum源下载(任选其一)

  • 下载docker官方ce版
[root@daniel ~]# wget https://download.docker.com/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo
  • 或者使用aliyun的docker-ce源
[root@daniel ~]# wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo

docker安装

[root@daniel ~]# yum clean all
[root@daniel ~]# yum install docker-ce -y

PS: 注意要安装docker-ce版,不要安装docker(否则可能安装1.13老版本)

启动服务

[root@daniel ~]# systemctl start docker
[root@daniel ~]# systemctl enable docker
[root@daniel ~]# systemctl status docker

查看版本信息

[root@daniel ~]# docker -v
Docker version 18.09.7, build 2d0083d
[root@daniel ~]# docker info
[root@daniel ~]# docker version
Client:
Version: 18.09.7
API version: 1.39
Go version: go1.10.8
Git commit: 2d0083d
Built: Thu Jun 27 17:56:06 2019
OS/Arch: linux/amd
Experimental: falseServer: Docker Engine - Community
Engine:
Version: 18.09.7
API version: 1.39 (minimum version 1.12)
Go version: go1.10.8
Git commit: 2d0083d
Built: Thu Jun 27 17:26:28 2019
OS/Arch: linux/amd64
Experimental: false

docker daemon管理

可以将client与Server进行分离,实现 远程docker连接 。为了实现它, 就需要对docker daemon进行相应的配置。

远程客户端主机# docker -H 容器宿主机IP version
Client:
Version: 18.09.7
API version: 1.39
Go version: go1.10.8
Git commit: 2d0083d
Built: Thu Jun 27 17:56:06 2019
OS/Arch: linux/amd
Experimental: false
Cannot connect to the Docker daemon at
tcp://10.1.1.11:2375. Is the docker daemon running?

配置过程

1, 修改docker配置文件前,请先关闭docker守护进程

[root@daniel ~]# systemctl stop docker

2, 通过/etc/docker/daemon.json文件对docker守护进程文件进行配置

[root@daniel ~]# vim /etc/docker/daemon.json
{"hosts": ["tcp://0.0.0.0:2375","unix:///var/run/docker.sock"]
}
[root@daniel ~]# netstat -ntlup | grep :2375
[root@daniel ~]# ls /var/run/docker.sock

PS: docker daemon默认侦听使用的是unix格式,侦听文件: UNIX:///run/docker.sock,添加tcp://0.0.0.0:2375可实现远程管理。

3, 添加/etc/docker/daemon.json后会导致docker daemon无法启动, 请先 修改如下文件内容:

 修改前:
[root@daniel ~]# vim /usr/lib/systemd/system/docker.service
[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd - H fd:// --containerd=/run/containerd/containerd.sock修改后:[root@daniel ~]# vim /usr/lib/systemd/system/docker.service
[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd

4, 修改完成后,一定要加载此配置文件

[root@daniel ~]# systemctl daemon-reload

5, 重新开启docker守护进程

[root@daniel ~]# systemctl start docker
[root@daniel ~]# netstat -ntlup | grep :2375
tcp6 0  0 ::: 2375 :::*
LISTEN  3318 /dockerd

6, 实例远程连接方法

远程客户端主机# docker -H 容器宿主机IP version

注意: 客户端远程连接不需要加端口号

特别注意: 远程客户端主机远程操作的权限非常大,请测试完后还原

小结: docker engine分为client和server,默认都在本地

四、镜像,容器,仓库

镜像(image): 镜像就是打包好的环境与应用。

容器(contanier): 容器就是运行镜像的实例. 镜像看作是静态的,容器是动态的。

仓库(repository): 存放多个镜像的一个仓库。

五、镜像常见操作

镜像主要分为两类:

  1. 操作系统类(如centos,ubuntu)

  2. 应用程序类

查看镜像列表

通过docker images命令查看当前镜像列表; 使用man docker-images得到参数说明

[root@daniel ~]# docker images

搜索镜像

通过docker search查找官方镜像; 使用man docker-search得到参数说明

[root@daniel ~]# docker search centos

拉取镜像

通过docker pull拉取(下载)镜像; 使用man docker-pull得到参数说明

此镜像大概 200 多M,网速要好
[root@daniel ~]# docker pull centos
或
[root@daniel ~]# docker pull docker.io/centos
名字为 search查找时得到的全名如果网速慢,可以试试阿里,腾讯,百度,网易等国内的镜像仓库,比如:
[root@daniel ~]# docker pull hub.c.163.com/library/centos:latest
[root@daniel ~]# docker images
REPOSITORY TAG IMAGE ID
CREATED SIZE
docker.io/centos latest 1e1148e4cc2c1 days ago  202 MB
hub.c.163.com/library/centos latest 328edcd84f1b16 months ago  193 MB

删除镜像

通过docker rmi删除镜像; man docker-rmi查看参数帮助

[root@daniel ~]# docker rmi hub.c.163.com/library/centos:latest

问题:如果镜像pull非常慢,怎么解决?

  1. docker镜像加速器

  2. 可以从网速好的宿主机上pull下来,然后 导出 给网速慢的宿主机 导入

镜像加速器

国内的几个互联网巨头都有自己的容器服务。这里以阿里云为例

阿里云容器镜像服务地址:https://cr.console.aliyun.com/cn-hangzhou/new 申请一个阿里账号登录


[root@daniel ~]# vim /etc/docker/daemon.json
{"registry-mirrors": ["https://42h8kzrh.mirror.aliyuncs.com"]
}
[root@daniel ~]# systemctl daemon-reload
[root@daniel ~]# systemctl restart docker

镜像导出

使用docker save保存(导出)镜像为一个tar文件

镜像导入

使用docker load导入

[root@daniel ~]# docker save centos -o /root/dockerimage_centos.latest

测试时可以将导出的文件scp传输到另一台宿主机测试。或者先删除本地的镜像再导入测试

[root@daniel ~]# docker load < /root/dockerimage_centos.latest

如果导入后看不到名称,可以使用docker tag命令改名称

[root@daniel ~]# docker images
REPOSITORY TAG IMAGE ID
CREATED SIZE
<none> <none>  9f38484d220f3 months ago  202 MB[root@daniel ~]# docker tag 9f38484d220f  docker.io/centos:latest[root@daniel ~]# docker images
REPOSITORY TAG IMAGE ID
CREATED SIZE
docker.io/centos latest  9f38484d220f3 months ago  202 MB

六、镜像仓库

官方自建镜像仓库

docker hub为最大的公开仓库,也就是官方仓库: https://hub.docker.com/

1, 没有账号的先上网申请账号





2, 回到宿主机登录账号与密码

# docker login
Login with your Docker ID to push and pull images from
Docker Hub. If you don't have a Docker ID, head over to
https://hub.docker.com to create one.
Username: linuxdaniel
Password:
Login Succeeded

3, tag你的镜像

我们从dockerhub上下载的公开镜像是不能直接上传的,要先tag(打标签,类似于重新指定路径并命名 )

[root@daniel ~]# docker push centos:latest
Error response from daemon: You cannot push a "root"
repository. Please rename your repository to
docker.io/<user>/<repo> (ex: docker.io/<user>/centos)[root@daniel ~]# docker tag centos:latest linuxdaniel/daniel_docker_repo:V1
[root@daniel ~]# docker push linuxdaniel/daniel_docker_repo:V1

4, push镜像到仓库

[root@daniel ~]# docker push linuxdaniel/daniel_docker_repo:V1

5, 验证

6, 登出账号

[root@daniel ~]# docker logout
Removing login credentials for https://index.docker.io/v1/

阿里云镜像仓库

登录阿里云账号,主页面上找产品–>云计算基础–> 容器镜像服务–>然后使用账号登录

登录成功后,做下列操作

1, 创建命名空间(命令空间和镜像仓库名称合到一起组成镜像的路径名称)


2, 创建镜像仓库,指定仓库名称


登出方法

使用docker logout接地址
# docker logout registry.cn-shenzhen.aliyuncs.com

harbor私有镜像仓库

Harbor是VMware公司开源了企业级Registry项目, 可以帮助用户快速搭建一个企业级的Docker registry服务.

harbor由python语言开发, 需要使用docker-compose工具进行启动

说明: docker-compose是容器编排工具,会在后面的docker三剑客中讲解

环境准备

再准备一台新的虚拟机(192.168.122.18)做harbor服务器

安装过程

1, 安装docker-compose

以下 3 种方法任选其一

安装方法1:

因为centos7上默认安装了python2.7,我们这里安装python2-pip,然后通过pip安装docker-compose模块

[root@harbor ~]# yum install epel-release -y
[root@harbor ~]# yum install python2-pip -y
[root@harbor ~]# pip install -i https://pypi.tuna.tsinghua.edu.cn/simple docker-compose
指定清华源安装速度较快[root@harbor ~]# docker-compose -v
docker-compose version 1.24.1, build 4667896b

安装方法2:

[root@harbor ~]# curl -L https://get.daocloud.io/docker/compose/releases/download/1.24.1/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
[root@harbor ~]# chmod +x /usr/local/bin/docker-compose

安装方法3:

[root@harbor ~]# yum install epel-release
[root@harbor ~]# yum install docker-compose
注意:此安装方法安装的版本较低,如果harbor版本太新,可能会不兼容

2, 在harbor服务器上安装docker-ce并启动docker服务

[root@harbor ~]# wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo
[root@harbor ~]# yum install docker-ce[root@harbor ~]# systemctl start docker
[root@harbor ~]# systemctl enable docker

3, 安装harbor

harbor分为离线包和在线包两种。在线包较小,但需要连网下载。我这里使用离线包

下载地址: https://github.com/goharbor/harbor/releases

我这里提供了 harbor-offline-installer-v1.8.2.tgz 给大家拷贝到harbor服务器上

[root@harbor ~]# tar xf harbor-offline-installer-v1.8.2.tgz -C /usr/local/
[root@harbor ~]# cd /usr/local/harbor/[root@harbor ~]# vim harbor.cfg
5 hostname = 192.168.122.18 将hostname改成harbor服务器的IP
27 harbor_admin_password = 123 admin用户的默认密码,我这里改为简单的 123[root@node1 harbor]# ./prepare
[root@harbor harbor]# ./install.sh
......
......
......
✔ ----Harbor has been installed and started
successfully.----Now you should be able to visit the admin portal at
http://192.168.122.18.
For more details, please visit
https://github.com/goharbor/harbor .

4,浏览器访问 http://192.168.122.18,登录进行配置




公开项目: 下载镜像不需要docker login登录,但上传镜像还是需要dockerlogin登录

私有项目: 都需要docker login登录才以上传下载

镜像上传下载操作

5, 在docker宿主机配置非https连接

因为docker用https通讯,所以还需要做证书,太麻烦。

配置 “insecure-registries”: [“harbor服务器IP”] 来使用http通讯

[root@daniel ~]# vim /etc/docker/daemon.json
{"registry-mirrors":
["https://42h8kzrh.mirror.aliyuncs.com"], 这里有一个逗号
"insecure-registries": ["192.168.122.18"]
}
[root@daniel ~]# systemctl restart docker

6, 在docker宿主机登下载一个测试镜像,并tag成 harborIP/项目名/镜像名:TAG

[root@daniel ~]# docker pull hello-world
[root@daniel ~]# docker tag hello-world 192.168.122.18/test/hello-world:v1

7, 登陆服务器,并push上传镜像

[root@daniel ~]# docker login 192.168.122.18
Username: admin
Password: 密码为前面修改好的 123
Login Succeeded[root@daniel ~]# docker push 192.168.122.18/test/hello-
world:v1不用了可以logout
[root@daniel ~]# docker logout 192.168.122.18

8, 浏览器界面验证

9, docker宿主机想要pull上传的镜像,可以这样做

删除镜像再重新从harbor仓库上下载
[root@daniel ~]# docker rmi 192.168.122.18/test/hello-world:v1私有项目里的镜像需要先登录,再pull(公共项目里的镜像不用登录就可以直接
pull,请自行测试)
[root@daniel ~]# docker login 192.168.122.18
Username: admin
Password: 密码为前面设置的 123
Login Succeeded[root@daniel ~]# docker pull 192.168.122.18/test/hello-world:v1

小结: 远程仓库

  • 官方仓库 缺点:网络问题

  • 国内云运营商提供的镜像仓库 优点:网速较好 缺点: 安全性考虑

  • 自建仓库 优点: 网速好,安全性也好 缺点: 自己维护,需要服务器和存储成本

七、容器常见操作

查看容器列表

列表所有状态的容器,现在为空列表

使用man docker-ps得到参数说明

[root@daniel ~]# docker ps -a

运行第一个容器

通过hello-world这个镜像,运行一个容器(没有定义容器名称,则为随机名称)

  • 当前docker-host(容器宿主机)如果有hello-world这个镜像,则直接使用
  • 如果没有相关镜像,则会从docker hub去下载(配置了镜像加速器的优先找加速器)

使用man docker-run得到参数说明

[root@daniel ~]# docker run hello-world

再次查看容器列表,多了一个容器,但它的状态是exited,此容器就是运行了一句Hello from Docker!就退出了(我这里容器名随机为silly_lovelace)

[root@daniel ~]# docker ps -a
CONTAINER ID IMAGE COMMAND
CREATED STATUS PORTS
NAMES
6e3f991b9e8a hello-world "/hello"3 minutes ago Exited ( 0 ) 2 minutes ago
silly_lovelace上面列表格式比较长,看起来有些不舒服。可以简单处理下,只查看重要的几列
[root@daniel ~]# docker ps -a |awk -F"[ ]{2}*" '{print $1"\t\t"$3"\t\t"$5"\t"$NF}'
CONTAINER ID COMMAND STATUS
NAMES
6e3f991b9e8a "/hello" Exited ( 0 ) 3
minutes ago silly_lovelace

问题: 为什么容器运行完hello-world后就退出了,而不是继续运行?

我们前面把容器比喻为轻量级虚拟机,但是容器实际上只是 进程 。进行运行完了当然就退出了, 除非是类似服务那样的守护进程。

容器运行命令或脚本

指定使用docker.io/centos镜像运行"echo haha"命令latest是默认的TAG标签,可以省略;如果是其它TAG就不能省略,否则会默认为latest

[root@daniel ~]# docker run centos:latest echo haha
haha

docker运行一个不间断的脚本, -d表示后台运行(后台运行表示不输出结果 到屏幕)

[root@daniel ~]# docker run -d centos /bin/bash -c "while true; do echo haha;sleep 3;done"

查看刚才运行的容器

只有不间断运行脚本的容器还在UP状态,其它都为Exited状态
[root@daniel ~]# docker ps -a |awk -F"[ ]{2}*" '{print $1"\t\t"$3"\t\t"$5"\t"$NF}'
CONTAINER ID COMMAND STATUS
NAMES
21086dab3efa "/bin/bash -c 'whi..." Up 1 minutes
sleepy_ride
495310e96d9f "echo haha" Exited (0) 3 minutes
ago unruffled_jepsen
6e3f991b9e8a "/hello" Exited (0) 15 minutes
ago silly_lovelace

查看容器运行结果

后面接容器ID,也可以接容器名称
[root@daniel ~]# docker logs 21086dab3efa

停止容器

[root@daniel ~]# docker stop 21086dab3efa

启动容器

[root@daniel ~]# docker start 21086dab3efa

查看容器的相关信息

[root@daniel ~]# docker inspect 21086dab3efa

运行容器并交互式操作

使用下面命令启动容器;-i指交互;-t指tty终端;--name是用来指定容器名称
[root@daniel ~]# docker run -i -t --name=c1 centos:latest /bin/bash
[root@f736fe36002c /]# cat /etc/redhat-release
CentOS Linux release 7.6.1810 (Core) 可以看到我们下载的centos是7.6版本
[root@f736fe36002c /]# uname -r
3.10.0-862.el7.x86_64 查看的内核却与宿主机
centos7.5一样,说明是共享宿主机的内核在容器内操作(我这里创建一个文件,然后退出)
[root@f736fe36002c /]# touch /root/daniel
[root@f736fe36002c /]# exit
exit

实验: 交互式操作退出后如何再查看或修改先前在容器里创建的文件?

不要再使用下面的命令了,因为名称冲突,会报错(换一个名称会启动一个新的容器)
[root@daniel ~]# docker run -i -t --name=c1 centos:latest /bin/bash

1 ,使用下面命令查看到c1容器已经为Exited状态;-l表示列表最近的容器

[root@daniel ~]# docker ps -l
CONTAINER ID IMAGE COMMAND
CREATED STATUS
PORTS NAMES
f736fe36002c centos:latest "/bin/bash"2 minutes ago Exited ( 0 ) 1 minutes ago
c1

2 ,启动容器

[root@daniel ~]# docker start c1

3 ,然后使用attach指令连接UP状态的容器(Exited状态的容器无法attach)

[root@daniel ~]# docker attach c1

4 ,验证文件,可以按需求修改

[root@f736fe36002c /]# ls /root/daniel -l
- rw-r--r-- 1 root root 0 Dec 19 12:30 /root/daniel
[root@f736fe36002c /]# exit
exit

5, commit提交成一个新的镜像;c63d63bff173为容器ID;test_image为新的镜像名称

[root@daniel ~]# docker commit c63d63bff173 test_image
sha256:bfb4e268cc6b683e1fc19346daf446ddd85dc7d75bcaa5cfd80
978ac271a913f

6 ,验证新的镜像

[root@daniel ~]# docker images |grep test_image
test_image latest bfb4e268cc6b47 seconds ago  202 MB

容器外指定容器运行命令

可以在宿主机通过exec指令传命令到容器中执行,但要求容器为UP状态

[root@daniel ~]# docker start c1在container1容器里创建文件并验证;man docker-exec查看帮助
[root@daniel ~]# docker exec c1 touch /root/123
[root@daniel ~]# docker exec c1 ls -l /root/123或者用下面的命令连接上去交互式操作
[root@daniel ~]# docker exec -it c1 /bin/bash

删除容器

UP状态的容器要先停止才能删除

[root@daniel ~]# docker stop 21086dab3efa
[root@daniel ~]# docker rm 21086dab3efa

批量删除所有容器

加-q参数只查看所有容器的ID
[root@daniel ~]# docker ps -aq
f736fe36002c
21086dab3efa
495310e96d9f
6e3f991b9e8a
停止所有容器
[root@daniel ~]# docker stop $(docker ps -aq)
删除所有容器
[root@daniel ~]# docker rm $(docker ps -aq)

小结:

  • docker ps -a : 列出本地的所有容器信息

  • docker run 参数选项 --name 容器名 镜像名:TAG 传给容器内部执行的命令

  • docker logs 容器名或容器ID: 输出容器内执行命令的结果

  • docker stop 容器名或容器ID: 停止容器

  • docker start 容器名或容器ID: 启动容器

  • docker attach 容器名或容器ID: 连接一个UP状态的容器,可以进去交互 (有bash环境的才可以)

  • docker exec 容器名或容器ID 命令: 不用连接容器,可以外部传命令给容器内部操作

  • docker exec -it 容器名或容器ID /bin/bash 连接容器交互

  • docker inspect 容器名或容器ID: 查看容器的属性

  • docker rm 容器名或容器ID: 删除容器

  • docker commit 容器名或容器ID 新的镜像名:TAG 将容器提交为一个镜像

需要记忆的核心命令:

  • docker ps -a

  • docker run ( 重难点 )

  • docker start ; docker stop;

  • docker commit

  • docker exec; docker exec -it 容器名或容器ID /bin/bash

  • docker rm

八、docker存储驱动

写时复制与用时分配

通过上面的学习,我们知道了一个镜像可以跑多个容器,如果每个容器都去复 制一份镜像内的文件系统,那么将会占用大量的存储空间。docker使用了 写时复制cow(copy-on-write) 和 用时分配(allocate-on-demand) 技术来 提高存储的利用率。

写时复制 :

  • 写时复制技术可以让多个容器共享同一个镜像的文件系统, 所有数据都从镜像中读取

  • 只有当要对文件进行写操作时,才从镜像里把要写的文件复制到自己的文件系统进行修改。所以无论有多少个容器共享同一个镜像,所做的写操作都是对从镜像中复制到自己的文件系统中的复本上进行,并不会修改镜像的源文件

  • 多个容器操作同一个文件,会在每个容器的文件系统里生成一个复本,每个容器修改的都是自己的复本,相互隔离,相互不影响

用时分配:

启动一个容器,并不会为这个容器预分配一些磁盘空间,而是当有新文件写入时,才按需分配新空间

联合文件系统

联合文件系统(UnionFS)就是把不同物理位置的目录合并mount到同一个目录中.

比如你可以将一个光盘与一个硬盘上的目录联合挂载到一起,然后对只读的光盘文件进行修改,修改的文件不存放回光盘进行覆盖,而是存放到硬盘目录。这样做达到了不影响光盘原数据,而修改的目的。

思考: 把光盘看作是docker里的image,而硬盘目录看作是container,你再想想看?

docker就支持aufs和overlay两种联合文件系统。

aufs

Docker最开始采用AUFS作为文件系统,也得益于AUFS分层的概念,实现了多个Container可以共享同一个image。

aufs(Another UnionFS),后来叫Alternative UnionFS,后来可能觉得不够霸气,叫成Advance UnionFS.

Docker最开始采用AUFS作为文件系统,也得益于AUFS分层的概念,实现了多个Container可以共享同一个image

除了最上面的一层为读写层之外,下面的其他的层都是只读的镜像层.

overlay

由于AUFS未并入Linux内核,且只支持Ubuntu,考虑到兼容性问题,在Docker 0.7版本中引入了存储驱动。 目前,Docker支持AUFS,OverlayFS,Btrfs,Device mapper,ZFS五种存储驱动.

目前, 在ubuntu发行版上默认存储方式为AUFS,CentOS发行版上的默认存储方式为Overlay或Overlay2

# docker info |grep "Storage Driver"
Storage Driver: overlay2
# lsmod |egrep 'aufs|overlay'
overlay  71964  7

centos上加载了overlay模块,从3.18版本内核开始,就进入了Linux内核主线

Overlay是Linux内核3.18后支持的(当前3.10内核加载模块也可以使用),也是一种Union FS,和AUFS的多层不同的是Overlay只有两层:一个upper文件系统和一个lower文件系统,分别代表Docker的容器层和镜像层…

OverlayFS底层目录称为lowerdir,高层目录称为upperdir。合并统一视图称为merged。当需要修改一个文件时,使用cow将文件从只读的Lower复制到可写的Upper进行修改,结果也保存在Upper层。在Docker中,底下的只读层就是image,可写层就是Container

下图分层图,镜像层是lowdir,容器层是upperdir,统一的视图层是merged层.

视图层就是给用户提供了一个统一的视角,隐藏了多个层的复杂性,对用户来说只存在一个文件系统。

从上图中可以看到:

  • 如果upperdir和lowerdir有同名文件时会用upperdir的文件

  • 读文件的时候,文件不在upperdir则从lowerdir读

  • 如果写的文件不在uppderdir在lowerdir,则从lowerdir里面copy到upperdir。

  • 不管文件多大,copy完再写,删除镜像层的文件只是在容器层生成whiteout文件标志(标记为删除,并不是真的删除) (后面的dockefile章节会体现出效果)

aufs,overlay,overlay2对比

aufs: 使用多层分层

overlay: 使用 2 层分层, 共享数据方式是通过 硬连接 ,只挂载一层,其他层通过最高层通过硬连接形式共享( 增加了磁盘inode的负担 )

overlay2: 使用 2 层分层, 驱动原生地支持多层lower overlay镜像(最多 128层),与overlay驱动对比,消耗更少的inode

不同阶段观察存储情况

新准备一台VM实例,重新安装docker(安装过程参考前面章节),进行如下测试

docker第 1 次启动前

在刚安装docker-ce第 1 次启动服务之前,/var/lib/下并没有docker这个目录

docker启动后

而第 1 次systemctl start docker启动后,则会产生/var/lib/docker目录

[root@vm2 ~]# systemctl start docker[root@vm2 ~]# ls -l /var/lib/docker
total 0
drwx------ 2 root root 24 Jun 23 15 : 30 builder
drwx------ 4 root root 92 Jun 23 15 : 30 buildkit
drwx------ 2 root root  6 Jun 23 15 : 30 containers
drwx------ 3 root root 22 Jun 23 15 : 30 image
drwxr-x--- 3 root root 19 Jun 23 15 : 30 network
drwx------ 3 root root 40 Jun 23 15 : 39 overlay2
drwx------ 4 root root 32 Jun 23 15 : 30 plugins
drwx------ 2 root root  6 Jun 23 15 : 39 runtimes
drwx------ 2 root root  6 Jun 23 15 : 30 swarm
drwx------ 2 root root  6 Jun 23 15 : 41 tmp
drwx------ 2 root root  6 Jun 23 15 : 30 trust
drwx------ 2 root root 25 Jun 23 15 : 30 volumes
[root@vm2 ~]# cd /var/lib/docker/overlay2/
[root@vm2 overlay2]# ls
total 0
brw------- 1 root root 8 , 3 Jul 26 14 : 10 backingFsBlockDev
drwx------ 2 root root  6 Jul 26 14 : 10 l

下载镜像后

[root@vm2 overlay2]# docker pull centos
Using default tag:latest
latest: Pulling from library/centos
8 ba884070f61: Pull complete
Digest:
sha256:a799dd8a2ded4a83484bbae769d97655392b3f86533ceb7dd96
bbac929809f3c
Status: Downloaded newer image for centos:latest
[root@vm2 overlay2]# pwd
/var/lib/docker/overlay2
[root@vm2 overlay2]# ls
23664d7a4167e74ee04838d87cd3568cc82be49f781bba2212b9bff942
bb8fa4 backingFsBlockDev l[root@vm2 overlay2]# ls
23664d7a4167e74ee04838d87cd3568cc82be49f781bba2212b9bff942
bb8fa4/
diff link[root@vm2 overlay2]# ls
23664d7a4167e74ee04838d87cd3568cc82be49f781bba2212b9bff942
bb8fa4/diff/anaconda-post.log bin dev etc home lib lib64 media
mnt opt proc root run sbin srv sys tmp usr var[root@vm2 overlay2]# cat
23664d7a4167e74ee04838d87cd3568cc82be49f781bba2212b9bff942
bb8fa4/link
5D7D6BY2V3FKMZHUU6VHK7ILWL[root@vm2 overlay2]# ll l
total 0
lrwxrwxrwx 1 root root 72 Jul 26 14:16
5D7D6BY2V3FKMZHUU6VHK7ILWL ->
../23664d7a4167e74ee04838d87cd3568cc82be49f781bba2212b9bff
942bb8fa4/diff
  • 下载完镜像,overlay2目录里多了一个23664…这样的目录,只有 1 层

  • 此目录内部的diff子目录记录每一层自己的数据

  • link记录该层链接目录(和overlay目录下l子目录里记录的链接是一致的)

  • l子目录中包含了很多软链接,使用短名称指向了其他层,短名称用于避免mount参数时达到页面大小的限制

运行容器后

[root@vm2 overlay2]# docker run -i -t --name=c1 centos:latest /bin/bash
[root@9169c38e6424 /]
同时按ctrl+p+q三键退出,保持容器为UP状态
[root@vm2 overlay2]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED
STATUS PORTS NAMES
9169 c38e6424 centos:latest "/bin/bash"  12 seconds ago
Up 10 seconds c1

容器运行后,再次查看overlay2目录下的情况



[root@vm2 overlay2]# ll 3652e67b65ebe7eaed7cc879f8470983181fc19fee2f3d72173e6766e28ec74/
total 8
drwxr-xr-x 2 root root  6 Jul 26 14 : 30 diff
- rw-r--r-- 1 root root 26 Jul 26 14 : 30 link
- rw-r--r-- 1 root root 57 Jul 26 14 : 30 lower
drwxr-xr-x 1 root root  6 Jul 26 14 : 30 merged
drwx------ 3 root root 18 Jul 26 14 : 30 work
  • lower指定了下层

  • work用来完成如copy-on_write的操作。

[root@vm2 overlay2]# cat 3652e67b65ebe7eaed7cc879f8470983181fc19fee2f3d72173e67666e28ec74/lower
l/UQF6DWQE64JXS3TEBUFOBSD3TY:l/5D7D6BY2V3FKMZHUU6VHK7ILWL[root@vm2 overlay2]# ls -l l/
total 0
lrwxrwxrwx 1 root root 72 Jul 26 14 : 16
5D7D6BY2V3FKMZHUU6VHK7ILWL -> ../23664d7a4167e74ee04838d87cd3568cc82be49f781bba2212b9bff
942bb8fa4/diff
lrwxrwxrwx 1 root root 72 Jul 26 14 : 30
KBKN2UECH7JGUJBUGIVHYV4ERX -> ../3652e67b65ebe7eaed7cc879f8470983181fc19fee2f3d72173e676
66e28ec74/diff
lrwxrwxrwx 1 root root 77 Jul 26 14 : 30
UQF6DWQE64JXS3TEBUFOBSD3TY -> ../3652e67b65ebe7eaed7cc879f8470983181fc19fee2f3d72173e676
66e28ec74-init/diff

通过上面的测试总结:

  • 用户看到的文件系统层为:
/var/lib/docker/overlay2/3652e67b65ebe7eaed7cc879f8470983181fc19fee2f3d72173e67666e28ec74/merged
  • 它由
/var/lib/docker/overlay2/3652e67b65ebe7eaed7cc879f8470983181fc19fee2f3d72173e67666e28ec74-init/diff/
和
/var/lib/docker/overlay2/23664d7a4167e74ee04838d87cd3568cc82be49f781bba2212b9bff942bb8fa4/diff/

联合挂载而成

  • 以下目录用于copy-on-write操作
/var/lib/docker/overlay2/3652e67b65ebe7eaed7cc879f8470983181fc19fee2f3d72173e67666e28ec74/work
  • 如果使用docker attach 容器名连接后在容器内创建文件的话,它会存放在
/var/lib/docker/overlay2/3652e67b65ebe7eaed7cc879f8470983181fc19fee2f3d72173e67666e28ec74/diff

小结:

  • docker在centos7目前使用的存储驱动为overlay2

  • docker通过写时复制(cow)和用时分配来提高存储的效率

  • aufs和ovelay属于联合文件系统

  • aufs是多层分层

  • overlay主要为 2 两层: lowerdir和upperdir

  • overlay2相比于overlay节省innode

九、容器里跑应用

前面我们熟悉了容器的常见操作,但容器中并没有跑过应用程序.而生产环境是要用容器来跑应用程序的。

宿主机上打开ip_forward , 因为我们下面要映射容器的端口到宿主机,只有打开ip_forward才能映射成功

[root@daniel ~]# vim /etc/sysctl.conf
net.ipv4.ip_forward = 1
[root@daniel ~]# sysctl -p

容器中运行httpd应用

回顾镜像:

  • 系统镜像

  • 应用镜像

首先我们通过系统镜像来跑httpd

案例 1 : 端口映射

利用官方centos镜像运行容器跑httpd服务,因为官方centos镜像里默认并没有安装httpd服务,所以需要我们自定义安装

docker内部跑httpd启动 80 端口,需要与docker_host(宿主机)进行端口映射,才能让客户端通过网络来访问

1, 运行容器httpd1; -p 8000:80的意思是把容器里的 80 端口映射为docker_host(宿主机)的 8000 端口

[root@daniel ~]# docker run -it -p 8000:80 --name=httpd1 centos:latest /bin/bash
[root@b0a9623d3920 /]# yum install httpd httpd-devel -y
Failed to get D-Bus connection: Operation not permitted
启动服务.这里用systemctl start httpd启动服务会报错,所以直接使用命
令启动
[root@b0a9623d3920 /]# httpd -k start
[root@b0a9623d3920 /]# ss -an |grep :80
tcp LISTEN 0  0 ::: 80
:::*

2, 这里如果exit退出的话,启动的服务也会关闭。同时按下 ctrl+q+p三键,可以实现退出容器并保持容器 后台运行

可以查看到容器仍然是UP状态
[root@daniel ~]# docker ps -l
CONTAINER ID IMAGE COMMAND
CREATED STATUS PORTS
NAMES
b0a9623d3920 centos:latest "/bin/bash"
1 minutes ago Up 1 minutes 0.0.0.0:8000-> 80 /tcp httpd1

3, 使用另一台机器浏览器访问 http://宿主机IP:8000 测试

案例 2 : 自定义httpd并提交为镜像

cenots镜像里并没有httpd,所以需要安装.但是如果每次启动一个容器都要安装一遍httpd是让人受不了的.所以我们在一个容器里安装一次,把想自定义的全做了,然后将此容器commit成一个新的镜像。

以后就用这个新镜像运行容器就可以不用再重复装环境了。

1, 运行容器httpd2,安装httpd相关软件并自定义配置

[root@daniel ~]# docker run -it --name=httpd2 centos:latest /bin/bash[root@82b985aea72c /]# yum install httpd httpd-devel -y[root@82b985aea72c /]# mkdir /www
[root@82b985aea72c /]# echo "main page" > /www/index.html修改 119 行和 131 行的家目录为/www
[root@82b985aea72c /]# vi /etc/httpd/conf/httpd.conf[root@82b985aea72c /]# exit
exit

2, exit退出后此容器就变为了Exited状态

[root@daniel ~]# docker ps -l
CONTAINER ID IMAGE COMMAND
CREATED STATUS PORTS
NAMES
82 b985aea72c centos:latest "/bin/bash"
5 minutes ago Exited (0) 6 seconds ago
httpd2

3, 将搭建好的环境commit成新的镜像( 此镜像相当于是自定义的,生产环境中可以按需求push到镜像仓库 )

[root@daniel ~]# docker commit httpd2 httpd_image

4, 将commit提交的镜像启动一个新的容器,并将端口 80 映射到宿主机的8001

[root@daniel ~]# docker run -d -p 8001:80 --name=httpd3  httpd_image /usr/sbin/httpd -D FOREGROUND
dcaca836b94655364749c064519ad66c8229657262465e7ea8194f2616980b61
[root@daniel ~]# lsof -i:8001
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
docker-pr 23130 root  4u IPv6 183572  0 t0 TCP
*:vcom-tunnel (LISTEN)

5, 使用另一台机器浏览器访问 http://宿主机IP:8001 测试

问题: /usr/sbin/httpd -D FOREGROUND能否做成自动传参?

答案: 可以,在dockerfile构建镜像章节会讨论。

案例 3 : docker数据卷挂载

问题: 当我有如下需求:

  • 容器内配置文件需要修改

  • 容器内数据(如: 如httpd家目录内的数据)需要保存

  • 不同容器间数据需要共享(如: 两个httpd容器家目录数据共享)

当容器删除时,里面的相关改变的数据也会删除,也就是说数据不能持久化保存。

我们可以将服务的配置文件,数据目录,日志目录等与宿主机的目录映射,把数据保持到宿主机上实现 数据持久化.

宿主机的目录也可以共享给多个容器使用。

将宿主机的目录(数据卷)挂载到容器中(配置文件也可以挂载)

1,先在宿主机创建一个目录,并建立一个内容不同的主页

[root@daniel ~]# mkdir /docker_www
[root@daniel ~]# echo daniel > /docker_www/index.html

2,运行容器httpd4, 将宿主机的/docker_www/目录挂载到容器中的/www/目录

[root@daniel ~]# docker run -d -p 8002:80 -v /docker_www/:/www --name=httpd4 httpd_image /usr/sbin/httpd -D FOREGROUND[root@daniel ~]# docker ps -l
CONTAINER ID IMAGE COMMAND
CREATED STATUS PORTS
NAMES
484d7432d7ef httpd_image "/usr/sbin/httpd
-..."  21 seconds ago Up 20 seconds
0.0.0.0: 8002->80/tcp httpd4

3, 使用另一台机器浏览器访问 http://宿主机IP:8002 测试

(注意: 如果访问不到主页,请检查是否关闭了selinux)

4, 尝试修改宿主机/docker_www/index.html的内容, 访问的结果也会随着修改而改变

拓展:

默认的centos镜像时间与我们差 8 小时, 所以这是时区的差异,可以用如下方式解决

# docker run -it -v /etc/localtime:/etc/localtime --name c2 centos /bin/bash

说明:

  • 因为我们是从docker官方pull下来的centos:latest镜像,它默认为UTC时区

  • 我们需要改成自己的时区,可以在启动容器时用-v /etc/localtime:/etc/localtime挂载映射

  • 如果你觉得每次都要挂载时区文件很麻烦,可以自定义把时区文件改好,保持为新的镜像再使用

# docker run -d --name httpd1 -p 8000:80 \
-v /httpd_www:/www -v /test/httpd.conf:/etc/httpd/conf/httpd.conf \httpd_image /usr/sbin/httpd - D FOREGROUND

说明:

  • /httpd_www/目录可以不用提前创建,它会自动帮我们创建

  • /test/httpd.conf此文件需要提前准备(配置文件里的家目录要改为/www)

  • 挂载后,通过修改宿主机的数据来达到修改容器内部数据的目地

案例4: 官方httpd镜像运行容器

参考: https://hub.docker.com/_/httpd

1, pull官方httpd镜像

[root@daniel ~]# docker search httpd
[root@daniel ~]# docker pull httpd

2, 运行容器

/data/www目录可以提前创建,也可以不用创建(它会帮我们自动创建)
[root@daniel ~]# docker run -d -p 8003:80 --name=httpd4 -v /data/www/:/usr/local/apache2/htdocs/ httpd:latest[root@daniel ~]# echo "new page" > /data/www/index.html

3, 使用另一台机器浏览器访问 http://宿主机IP:8003 测试

容器中运行mysql或mariadb应用

案例1:官方mysql镜像运行容器

1, 先拉取mysql镜像

[root@daniel ~]# docker pull mysql:5.6

2, 启动容器

--restart=always表示重启docker服务后会自动重启
- e MYSQL_ROOT_PASSWORD= 123 指定mysql的root用户密码
[root@daniel ~]# docker run -d -p 3306:3306 --name=mysql1 -v /data/mysql:/var/lib/mysql --restart=always -e MYSQL_ROOT_PASSWORD=123 mysql:5.6启动后查看宿主机的/data/mysql/目录,发现已经初始化数据了
[root@daniel ~]# ls /data/mysql/
auto.cnf ibdata1 ib_logfile0 ib_logfile1 mysql
performance_schema

更多参数和详细说明请参考:https://hub.docker.com/_/mysql

3, 连接上去,按需求自由使用

[root@daniel ~]# mysql -h 127.0.0.1 -u root -p123

案例2:centos镜像自定义mariadb环境

[root@daniel ~]# docker run -it -d -p 3307:3306 -v /data/mysql2:/var/lib/mysql --restart=always --name=mariadb2 centos:latest /bin/bash[root@daniel ~]# docker attach mariadb2[root@7dccf1c72315 /]# yum install mariadb-server -y
[root@7dccf1c72315 /]# mysql_install_db --datadir=/var/lib/mysql/ --user=mysql
[root@7dccf1c72315 /]# mysqld_safe --defaults-file=/etc/my.cnf &
[root@7dccf1c72315 /]# mysql
MariaDB [(none)]> grant all on *.* to 'abc'@'%' identified by ' 123 ';
MariaDB [(none)]> flush privileges;
MariaDB [(none)]> quit
[root@7dccf1c72315 /]#
最后按ctrl+p+q退出并保持容器后台运行

2, 找另一台远程连接测试OK

# mysql -h docker宿主机IP -u abc -p123 -P 3307

容器中运行nginx应用

参考: https://hub.docker.com/_/nginx

案例1: 官方nginx镜像运行容器

1, pull拉取镜像

[root@daniel ~]# docker pull nginx

2, 准备一个nginx.conf配置文件

[root@daniel ~]# mkdir /data/nginx/etc -p
准备下面的配置文件(自己写一个,或者拷贝一个都可以)
[root@daniel ~]# ls /data/nginx/etc/nginx.conf

3, 运行容器,并准备一个主页文件

[root@daniel ~]# docker run -d -p 8004:80 --restart=always --name=nginx1 -v /data/nginx/html:/usr/share/nginx/html -v /data/nginx/etc/nginx.conf:/etc/nginx/nginx.conf -v /data/nginx/log:/var/log/nginx nginx:latest[root@daniel ~]# echo "nginx main page" > /data/nginx/html/index.html

4, 使用另一台机器浏览器访问 http://宿主机IP:8003 测试

5 ,如果想要修改nginx配置文件,可以按下面步骤来实现

[root@daniel ~]# vim /data/nginx/etc/nginx.conf
再重启容器
[root@daniel ~]# docker stop nginx1
[root@daniel ~]# docker start nginx1

练习: 请使用centos镜像自定义nginx环境

容器中运行tomcat应用

参考: https://hub.docker.com/_/tomcat

案例1: 官方tomcat镜像运行容器

[root@daniel ~]# docker run -d -p 8080:8080 --name=tomcat1 tomcat:latest

访问http://docker宿主机IP:8080验证

课后兴趣练习: 搜索官方各种应用镜像,并应用按需求先修改配置文件

十、使用Dockerfile构建镜像

除了使用docker commit把自定义容器提交成镜像外,还可以使用Dockerfile来构建自定义镜像。

什么是Dockerfile?

答: Dockerfile把构建镜像的步骤都写出来,然后按顺序执行实现自动构建镜像。就类似于脚本文件,ansible的playbook,saltstack的sls文件等。

dockerfile指令

通过man dockerfile可以查看到详细的说明,我这里简单的翻译并列出常用的指令

1, FROM

FROM指令用于指定其后构建新镜像所使用的基础镜像。

FROM指令必是Dockerfile文件中的首条命令。

FROM指令指定的基础image可以是官方远程仓库中的,也可以位于本地仓库,优先本地仓库。

格式:FROM <image>:<tag>
例:FROM centos:latest

2, RUN

RUN指令用于在 构建 镜像中执行命令,有以下两种格式:

  • shell格式
格式:RUN <命令>
例:RUN echo daniel > /var/www/html/index.html
  • exec格式
格式:RUN ["可执行文件", "参数1", "参数2"]
例:RUN ["/bin/bash", "-c", "echo daniel > /var/www/html/index.html"]

注意: 按优化的角度来讲:当有多条要执行的命令,不要使用多条RUN,尽量使用&&符号与\符号连接成一行。因为多条RUN命令会让镜像建立多层(总之就是会变得臃肿了

day91~93-Paas云平台_docker容器相关推荐

  1. re.containerbase.startinternal 子容器启动失败_微服务架构:基于微服务和Docker容器技术的PaaS云平台架构设计(微服务架构实施原理)...

    走过路过不要错过 点击蓝字关注我们 基于微服务架构和Docker容器技术的PaaS云平台建设目标是给我们的开发人员提供一套服务快速开发.部署.运维管理.持续开发持续集成的流程.平台提供基础设施.中间件 ...

  2. 中国人寿如何基于容器搭建金融PaaS云平台

    6月28日,Rancher Labs在北京举办了Container Day 2018容器技术大会.在大会上,Rancher Labs CEO及联合创始人梁胜博士.中国人寿研发中心开发五部副总经理王川. ...

  3. 基于微服务和Docker容器技术的PaaS云平台架构设计

    本文讲的是基于微服务和Docker容器技术的PaaS云平台架构设计[编者的话]在系统架构上,PaaS云平台主要分为微服务架构.Docker容器技术.DveOps三部分,这篇文章重点介绍微服务架构的实施 ...

  4. 中国人寿如何基于容器搭建金融PaaS云平台 1

    6月28日,Rancher Labs在北京举办了Container Day 2018容器技术大会.在大会上,Rancher Labs CEO及联合创始人梁胜博士.中国人寿研发中心开发五部副总经理王川. ...

  5. 基于微服务和Docker的PaaS云平台架构设计

    基于微服务架构和Docker容器技术的PaaS云平台建设目标是给我们的开发人员提供一套服务快速开发.部署.运维管理.持续开发持续集成的流程.平台提供基础设施.中间件.数据服务.云服务器等资源,开发人员 ...

  6. ARM全国产云平台部署容器实战

    如何基于国产CPU的云平台构建容器管理平台?  目录 第一节 基于国产CPU的服务器 2 第二节 国产云平台 6 1.安装云平台 9 1.1启动ARM服务器,从U盘启动 9 1.2 ARM服务器BIO ...

  7. 金融信创优秀解决方案名单权威发布,信创PaaS云平台实力入选

    近日,中国人民银行直属机构金融信创生态实验室(以下简称:金融信创实验室)发布了<金融信创优秀解决方案 第二期•产业篇>,谐云的"PaaS云平台解决方案"成功入选.在进一 ...

  8. PaaS云平台技术架构及发展趋势研讨会 暨中服软件战略融资发布会成功召开

    2017年3月17日下午,由中服软件主办的"PaaS云平台技术架构及发展趋势研讨会暨中服软件战略融资发布会"在陕西省科技资源统筹中心成功召开.此次会议还受到了陕西省大数据与云计算产 ...

  9. 为PaaS云平台提供整合的全栈式监控

    作为一项日益受到欢迎的技术,平台即服务(Platform-as-a-Service,PaaS)可以在云端部署能够通过Web访问的应用.借助PaaS,用户不必关注详细的执行信息,例如操作系统.资源分配. ...

最新文章

  1. kubernetes1.8.4 安装指南 -- 6. 安装kubernetes master
  2. 2018java基础面试题(我自己用的,面试好多家公司基本会问到的问题和技术)
  3. ini_set ini_get 可操作配置参数列表 设置默认编码等
  4. k8s学习(一)——kubectl与api-server之间的交互核心过程
  5. 在Windows 2000下优化Oracle9i性能
  6. js进阶 10-9 -of-type型子元素伪类选择器
  7. python文件操作笔记
  8. javascript第四弹——变量、作用域、内存
  9. 解决scrollView上subView下移20point问题的一种方式
  10. java找最长连续号段,字符串—寻找最长连续子串
  11. 2020-03-19
  12. STM32F103系列引脚定义-功能图
  13. recvfrom的addrlen参数
  14. GhostXP_SP2电脑公司特别版_v7.8
  15. JAVA-SUST实验一 JSP技术及JSP语法基础
  16. java计算机毕业设计政务大厅管理系统源码+数据库+系统+部署+lw文档
  17. 网络安全与管理 整理
  18. 学美工设计怎么找一家好的培训机构
  19. 几种常见的传统汽车总线传输通信技术
  20. 一段通过java 得到svn log 然后过滤一些文字, 最后打印出来的shell

热门文章

  1. 错误: 找不到或无法加载主类 com.sxt.ceshi.Demo166
  2. Three.js凹凸贴图bumpMap和法线贴图.normalMap
  3. RTMP转HTTP-FLV视频流web端应用流程记录
  4. 聚焦网络攻击|知道创宇云安全2018年度网络安全态势报告
  5. 自动驾驶寻找「商业闭环」
  6. 音视频 FLV格式解析
  7. 移动端APP测试总结--转
  8. m4a转wav格式方法和步骤
  9. Java 从word中提取文字信息(开发笔记)
  10. Laravel Scout 包在 Elasticsearch 中的使用记录