导图社区 docker使用说明
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。本思维导图包括docker使用说明,涵盖基础以及部门原理,很全面,希望对你有帮助!
编辑于2019-09-18 12:32:11Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。本思维导图包括docker使用说明,涵盖基础以及部门原理,很全面,希望对你有帮助!
说话不只是一种“感觉”,还是一门“技术”!就像烹饪有食谱一样,说话也有它的“秘方”。古往今来,但凡不通说话之道者,都难成大事,而能成事者,一定在语言方面具有其独特的能力。一句恰到好处的话,甚至可以改变一个人的命运。人际沟通中怎样措辞?怎样把握说话的场合和时机?如何领略说话精髓,悟透说话之道,很快在众人中脱颖而出?《所谓情商高就是会说话》读书笔记,思维导图快收下!
社区模板帮助中心,点此进入>>
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。本思维导图包括docker使用说明,涵盖基础以及部门原理,很全面,希望对你有帮助!
说话不只是一种“感觉”,还是一门“技术”!就像烹饪有食谱一样,说话也有它的“秘方”。古往今来,但凡不通说话之道者,都难成大事,而能成事者,一定在语言方面具有其独特的能力。一句恰到好处的话,甚至可以改变一个人的命运。人际沟通中怎样措辞?怎样把握说话的场合和时机?如何领略说话精髓,悟透说话之道,很快在众人中脱颖而出?《所谓情商高就是会说话》读书笔记,思维导图快收下!
Docker
底层原理
Linux Namespaces
名字空间是:Linux内核一个强大的特性。每个容器都有自己单独的名字空间,运行在其中的应用都像是在 独立的操作系统中运行一样。名字空间保证了容器之间彼此互不影响。
1. UTS
UTS("UNIX Time-sharing System")名字空间允许每个容器拥有独立的hostname和domain name,使其在 网络上可以被视作一个独立的节点而非主机上的一个进程。
系统调用参数:CLONE_NEWUTS
隔离内容:
主机名和域名
2. IPC
IPC全称 Inter-Process Communication,是Unix/Linux下进程间通信的一种方式,IPC有共享内存、信号量、消息队列等方法。所以,为了隔离,我们也需要把IPC给隔离开来,这样,只有在同一个Namespace下的进程才能相互通信。如果你熟悉IPC的原理的话,你会知道,IPC需要有一个全局的ID,即然是全局的,那么就意味着我们的Namespace需要对这个ID隔离,不能让别的Namespace的进程看到。
系统调用参数:CLONE_NEWIPC
隔离内容:
信号量、消息队列和共享内存
3. PID
不同用户的进程就是通过pid名字空间隔离开的,且不同名字空间中可以有相同pid。所有的LXC进程在 Docker中的父进程为Docker进程,每个LXC进程具有不同的名字空间。同时由于允许嵌套,因此可以很 方便的实现嵌套的Docker容器。
系统调用参数:CLONE_NEWPID
隔离内容:
进程编号
4. Network
有了pid名字空间,每个名字空间中的pid能够相互隔离,但是网络端口还是共享host的端口。网络隔离是通过net 名字空间实现的,每个net名字空间有独立的网络设备,IP地址,路由表,/proc/net目录。这样每 个容器的网络就能隔离开来。Docker默认采用veth的方式,将容器中的虚拟网卡同host上的一个Docker 网桥docker0连接在一起。
系统调用参数:CLONE_NEWNS
隔离内容:
网络设备、网络栈、端口等
5. Mount
类似chroot,将一个进程放到一个特定的目录执行。mnt名字空间允许不同名字空间的进程看到的文件结 构不同,这样每个名字空间中的进程所看到的文件目录就被隔离开了。同chroot不同,每个名字空间中的 容器在 /proc/mounts的信息只包含所在名字空间的 mount point
系统调用参数:CLONE_NEWNS
隔离内容:
挂载点(文件系统)
6. User
同进程 ID 一样,用户 ID 和组 ID 在命名空间内外是不一样的,并且在不同命名空间内可以存在相同的 ID
1. 系统调用参数:CLONE_NEWUSER
隔离内容:
用户和用户组
LXC
RunC
当前docker的引擎
基本概念
镜像
Docker 镜像 我们都知道,操作系统分为内核和用户空间。对于 Linux 而言,内核启动后,会挂载 root 文件系统为其提供用户空间支持。而 Docker 镜像(Image),就相当于是一个 root 文件系统。比如官方镜像 ubuntu:18.04 就包含了完整的一套 Ubuntu 18.04 最小系统的 root 文件系统。 Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。 分层存储 因为镜像包含操作系统完整的 root 文件系统,其体积往往是庞大的,因此在 Docker 设计时,就充分利用 Union FS 的技术,将其设计为分层存储的架构。所以严格来说,镜像并非是像一个 ISO 那样的打包文件,镜像只是一个虚拟的概念,其实际体现并非由一个文件组成,而是由一组文件系统组成,或者说,由多层文件系统联合组成。 镜像构建时,会一层层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。比如,删除前一层文件的操作,实际不是真的删除前一层的文件,而是仅在当前层标记为该文件已删除。在最终容器运行的时候,虽然不会看到这个文件,但是实际上该文件会一直跟随镜像。因此,在构建镜像的时候,需要额外小心,每一层尽量只包含该层需要添加的东西,任何额外的东西应该在该层构建结束前清理掉。 分层存储的特征还使得镜像的复用、定制变的更为容易。甚至可以用之前构建好的镜像作为基础层,然后进一步添加新的层,以定制自己所需的内容,构建新的镜像。 关于镜像构建,将会在后续相关章节中做进一步的讲解
容器
Docker 容器 镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的 类 和 实例 一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。 容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的 命名空间。因此容器可以拥有自己的 root 文件系统、自己的网络配置、自己的进程空间,甚至自己的用户 ID 空间。容器内的进程是运行在一个隔离的环境里,使用起来,就好像是在一个独立于宿主的系统下操作一样。这种特性使得容器封装的应用比直接在宿主运行更加安全。也因为这种隔离的特性,很多人初学 Docker 时常常会混淆容器和虚拟机。 前面讲过镜像使用的是分层存储,容器也是如此。每一个容器运行时,是以镜像为基础层,在其上创建一个当前容器的存储层,我们可以称这个为容器运行时读写而准备的存储层为 容器存储层。 容器存储层的生存周期和容器一样,容器消亡时,容器存储层也随之消亡。因此,任何保存于容器存储层的信息都会随容器删除而丢失。 按照 Docker 最佳实践的要求,容器不应该向其存储层内写入任何数据,容器存储层要保持无状态化。所有的文件写入操作,都应该使用 数据卷(Volume)、或者绑定宿主目录,在这些位置的读写会跳过容器存储层,直接对宿主(或网络存储)发生读写,其性能和稳定性更高。 数据卷的生存周期独立于容器,容器消亡,数据卷不会消亡。因此,使用数据卷后,容器删除或者重新运行之后,数据却不会丢失。
仓库
Docker Registry 镜像构建完成后,可以很容易的在当前宿主机上运行,但是,如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry 就是这样的服务。 一个 Docker Registry 中可以包含多个 仓库(Repository);每个仓库可以包含多个 标签(Tag);每个标签对应一个镜像。 通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本。我们可以通过 <仓库名>:<标签> 的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签。 以 Ubuntu 镜像 为例,ubuntu 是仓库的名字,其内包含有不同的版本标签,如,16.04, 18.04。我们可以通过 ubuntu:16.04,或者 ubuntu:18.04 来具体指定所需哪个版本的镜像。如果忽略了标签,比如 ubuntu,那将视为 ubuntu:latest。 仓库名经常以 两段式路径 形式出现,比如 jwilder/nginx-proxy,前者往往意味着 Docker Registry 多用户环境下的用户名,后者则往往是对应的软件名。但这并非绝对,取决于所使用的具体 Docker Registry 的软件或服务。 Docker Registry 公开服务 Docker Registry 公开服务是开放给用户使用、允许用户管理镜像的 Registry 服务。一般这类公开服务允许用户免费上传、下载公开的镜像,并可能提供收费服务供用户管理私有镜像。 最常使用的 Registry 公开服务是官方的 Docker Hub,这也是默认的 Registry,并拥有大量的高质量的官方镜像。除此以外,还有 CoreOS 的 Quay.io,CoreOS 相关的镜像存储在这里;Google 的 Google Container Registry,Kubernetes 的镜像使用的就是这个服务。 由于某些原因,在国内访问这些服务可能会比较慢。国内的一些云服务商提供了针对 Docker Hub 的镜像服务(Registry Mirror),这些镜像服务被称为加速器。常见的有 阿里云加速器、DaoCloud 加速器 等。使用加速器会直接从国内的地址下载 Docker Hub 的镜像,比直接从 Docker Hub 下载速度会提高很多。在 安装 Docker 一节中有详细的配置方法。 国内也有一些云服务商提供类似于 Docker Hub 的公开服务。比如 时速云镜像仓库、网易云镜像服务、DaoCloud 镜像市场、阿里云镜像库 等。 私有 Docker Registry 除了使用公开服务外,用户还可以在本地搭建私有 Docker Registry。Docker 官方提供了 Docker Registry镜像,可以直接使用做为私有 Registry 服务。在 私有仓库 一节中,会有进一步的搭建私有 Registry 服务的讲解。 开源的 Docker Registry 镜像只提供了 Docker Registry API 的服务端实现,足以支持 docker 命令,不影响使用。但不包含图形界面,以及镜像维护、用户管理、访问控制等高级功能。在官方的商业化版本 Docker Trusted Registry 中,提供了这些高级功能。 除了官方的 Docker Registry 外,还有第三方软件实现了 Docker Registry API,甚至提供了用户界面以及一些高级功能。比如,Harbor 和 Sonatype Nexus。
安装
Linux安装
https://docker_practice.gitee.io/install/centos.html
使用 yum 安装
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
鉴于国内网络问题,强烈建议使用国内源,官方源请在注释中查看。 执行下面的命令添加 yum 软件源: $ sudo yum-config-manager \ --add-repo \ https://mirrors.ustc.edu.cn/docker-ce/linux/centos/docker-ce.repo 注:yum-config-manager: command not found ,这个是因为系统默认没有安装这个命令,这个命令在yum-utils 包里,可以通过命令yum -y install yum-utils # 官方源 # $ sudo yum-config-manager \ # --add-repo \ # https://download.docker.com/linux/centos/docker-ce.repo 如果需要测试版本的 Docker CE 请使用以下命令: $ sudo yum-config-manager --enable docker-ce-test 如果需要每日构建版本的 Docker CE 请使用以下命令: $ sudo yum-config-manager --enable docker-ce-nightly
安装 Docker CE
更新 yum 软件源缓存,并安装 docker-ce。 $ sudo yum makecache fast $ sudo yum install docker-ce
使用脚本自动安装
$ curl -fsSL get.docker.com -o get-docker.sh $ sudo sh get-docker.sh --mirror Aliyun
启动 Docker CE
$ sudo systemctl enable docker $ sudo systemctl start docker
测试 Docker 是否安装正确
$ docker run hello-world Unable to find image 'hello-world:latest' locally latest: Pulling from library/hello-world d1725b59e92d: Pull complete Digest: sha256:0add3ace90ecb4adbf7777e9aacf18357296e799f81cabc9fde470971e499788 Status: Downloaded newer image for hello-world:latest Hello from Docker! This message shows that your installation appears to be working correctly. To generate this message, Docker took the following steps: 1. The Docker client contacted the Docker daemon. 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. (amd64) 3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading. 4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal. To try something more ambitious, you can run an Ubuntu container with: $ docker run -it ubuntu bash Share images, automate workflows, and more with a free Docker ID: https://hub.docker.com/ For more examples and ideas, visit: https://docs.docker.com/get-started/
安装后的配置文件:
没有/etc/sysconfig/docker这个配置文件 vim /lib/systemd/system/docker.service
Windows安装
官网下载,点击下一步安装
基础用法
基本命令
镜像管理
Docker 运行容器前需要本地存在对应的镜像,如果本地不存在该镜像,Docker 会从镜像仓库下载该镜像。
查看本地镜像
docker images
docker image ls
列表包含了 仓库名、标签、镜像 ID、创建时间 以及 所占用的空间。 其中仓库名、标签在之前的基础概念章节已经介绍过了。镜像 ID 则是镜像的唯一标识,一个镜像可以对应多个 标签。
docker image ls ubuntu(镜像仓库名字)
根据仓库名列出镜像
docker image ls ubuntu:18.04(镜像名字)
列出特定的某个镜像,也就是说指定仓库名和标签
docker image ls -a
显示包括中间层镜像在内的所有镜像
docker image ls -f since=mongo:3.2
docker image ls 还支持强大的过滤器参数 --filter,或者简写 -f。之前我们已经看到了使用过滤器来列出虚悬镜像的用法,它还有更多的用法。比如,我们希望看到在 mongo:3.2 之后建立的镜像
docker system df
查看镜像、容器、数据卷所占用的空间
获取镜像
docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]
具体的选项可以通过 docker pull --help 命令看到,这里我们说一下镜像名称的格式。 Docker 镜像仓库地址:地址的格式一般是 <域名/IP>[:端口号]。默认地址是 Docker Hub。 仓库名:如之前所说,这里的仓库名是两段式名称,即 <用户名>/<软件名>。对于 Docker Hub,如果不给出用户名,则默认为 library,也就是官方镜像。
例:docker pull ubuntu:18.04
查找网络镜像
docker search nginx
删除镜像
docker image rm [选项] <镜像1> [<镜像2> ...]
<镜像> 可以是 镜像短 ID、镜像长 ID、镜像名 或者 镜像摘要
创建镜像
docker commit
docker commit 意味着所有对镜像的操作都是黑箱操作,生成的镜像也被称为 黑箱镜像,换句话说,就是除了制作镜像的人知道执行过什么命令、怎么生成的镜像,别人根本无从得知。而且,即使是这个制作镜像的人,过一段时间后也无法记清具体在操作的。虽然 docker diff 或许可以告诉得到一些线索,但是远远不到可以确保生成一致镜像的地步。这种黑箱镜像的维护工作是非常痛苦的。
docker commit [选项] <容器ID或容器名> [<仓库名>[:<标签>]]
例:docker commit -m "修改增加内容" -a "yao" webserver nginx:v2
-m:--message 提交信息
-a:--author 作者信息
webserver:基础镜像名字(也可以是ID)
nginx:v2:指定创建的镜像名字
dockerfile
容器管理
查看本机容器
docker ps
查看运行中的容器
docker ps -a
查看所有容器
新建并启动容器
创建容器
docker create --name test1 centos:centos7.5.1804
创建运行容器
docker run -d -p 5000:5000 --name test2 centos:centos7.5.1804 python app.py
-d
让容器后台运行
-p
本地和容器内部端口映射
--name
容器名字
python app.py
容器启动时运行的命令
创建交互式容器
docker -dit --name test3 centos:centos7.5.1804
加了d参数退出不会停止
docker -it --name test3 centos:centos7.5.1804
退出容器会停止
-i -t 参数 docker exec 后边可以跟多个参数,这里主要说明 -i -t 参数。 只用 -i 参数时,由于没有分配伪终端,界面没有我们熟悉的 Linux 命令提示符,但命令执行结果仍然可以返回。 当 -i -t 参数一起使用时,则可以看到我们熟悉的 Linux 命令提示符。
重启容器
docker restart test1(容器名字)
退出容器
停止容器
docker container stop test1(容器名字)
运行停止状态的容器
docker start test1(容器名字)
进入容器
在使用 -d 参数时,容器启动后会进入后台。
docker attach
docker attach test1
注意: 如果从这个 stdin 中 exit,会导致容器的停止。
docker exec
docker exec 后边可以跟多个参数,这里主要说明 -i -t 参数。 只用 -i 参数时,由于没有分配伪终端,界面没有我们熟悉的 Linux 命令提示符,但命令执行结果仍然可以返回。 当 -i -t 参数一起使用时,则可以看到我们熟悉的 Linux 命令提示符。
docker exec -it test1 bash
如果从这个 stdin 中 exit,不会导致容器的停止
退出容器:进入容器中输入exit
删除容器
docker container rm reverent_dijkstra(容器名字)
可以使用 docker container rm 来删除一个处于终止状态的容器。
docker container rm -f reverent_dijkstra(容器名字)
删除一个运行中的容器
docker container prune
清理所有处于终止状态的容器
导出和导入容器
导出容器
docker export 7691a814370e(CONTAINER ID) > ubuntu.tar
导入容器快照
cat ubuntu.tar | docker import - test/ubuntu:v1.0
可以使用 docker import 从容器快照文件中再导入为镜像
docker import http://example.com/exampleimage.tgz example/imagerepo
通过指定 URL 或者某个目录来导入
其他命令
docker 容器命名和重命名
容器命名语法:docker run -d --name 容器实例名 容器镜像名 要执行的命令
容器重命名语法: docker rename 旧容器名 新容器名
创建docker容器实例时指定主机名
语法:docker run -it --name 容器名 -h 挃定主机名 镜像 /bin/bash
docker run -it --name docker1 -h docker_rds1 centos:centos7.5.1804 /bin/bash
从容器内拷贝文件到主机
docker cp 容器ID:容器内路径 目的主机路径
网络
网络模型
docker网络初始化的过程如下
初始化设备 —> 初始化bridge —> 初始化iptables —> 初始化ip foward(内核路由转发) — > register network job function —> end
一、 bridge方式(默认)
这个驱动是docker默认设置,我们安装好docker后你会发现默认会创建一个叫docker0的网桥,那么创建好的容器会默认使用这个网桥。这个其实就是linux bridge,在单机内使用网桥模式可以满足,与外界通信那么这里会用到NAT。
Bridge 桥接模式的实现步骤主要如下
Bridge 桥接模式的实现步骤主要如下: (1) Docker Daemon 利用 veth pair 技术,在宿主机上创建两个虚拟网络接口设备 假设为veth0 和 veth1。 而 veth pair 技术的特性可以保证无论哪一个 veth 接收到网络报文,都会将报文传输给另一方。 (2) Docker Daemon 将 veth0 附加到 Docker Daemon 创建的 docker0 网桥上。 保证宿主机的网络报文可以发往 veth0; (3) Docker Daemon 将 veth1 添加到 Docker Container 所属的 namespace 下,并被改名为 eth0。 如此一来,保证宿主机的网络报文若发往 veth0,则立即会被 eth0 接收 实现宿主机到Docker Container 网络的联通性; 同时,也保证 Docker Container 单独使用 eth0,实现容器网络环境的隔离性。 bridge 桥接模式下的 Docker Container 在使用时,并非为开发者包办了一切。 最明显的是,该模式下 Docker Container 不具有一个公有 IP, 即和宿主机的 eth0 不处于同一个网段。导致的结果是宿主机以外的世界不能直接和容器进行通信。 虽然 NAT 模式经过中间处理实现了这一点 但是 NAT 模式仍然存在问题与不便,如:容器均需要在宿主机上竞争端口,容器 内部服务的访问者需要使用服务发现获知服务的外部端口等。 另外 NAT 模式由于是在三层 网络上的实现手段,故肯定会影响网络的传输效率。
二、 none方式
此模式下创建容器是不会为容器配置任何网络参数的,如:容器网卡、IP、通信路由等,全部需要自己去配置。
三、 host方式
此模式创建的容器没有自己独立的网络命名空间,是和物理机共享一个Network Namespace,并且共享物理机的所有端口与IP,并且这个模式认为是不安全的。
host 模式是 bridge 桥接模式很好的补充。 采用 host 模式的 Docker Container,可以直接使用 宿主机的 IP 地址与外界进行通信,若宿主机的 eth0 是一个公有 IP, 那么容器也拥有这个公有 IP。 同时容器内服务的端口也可以使用宿主机的端口,无需额外进行 NAT 转换。 当然,有这样的方便,肯定会损失部分其他的特性, 最明显的是 Docker Container 网络环境隔离性的弱化, 即容器不再拥有隔离、独立的网络栈。 另外,使用 host 模式的 Docker Container 虽 然可以让容器内部的服务和传统情况无差别、无改造的使用, 但是由于网络隔离性的弱化,该容器会与宿主机共享竞争网络栈的使用; 另外,容器内部将不再拥有所有的端口资源, 原因是部分端口资源已经被宿主机本身的服务占用, 还有部分端口已经用以 bridge 网络模式容器的端口映射。
四、 container复用方式
此模式和host模式很类似,只是此模式创建容器共享的是其他容器的IP和端口而不是物理机,此模式容器自身是不会配置网络和端口,创建此模式容器进去后,你会发现里边的IP是你所指定的那个容器IP并且端口也是共享的,而且其它还是互相隔离的,如进程等。
默认
部分命令
docker network ls
#查看本机网络详情,默认有bridge、host、null
docker network inspect bridge
#查看某一个类型的网络情况
创建docker 静态化IP
容器之间的link
A. --link 需要互联的容器name
用得少
docker run -dit --name test1 centos /bin/bash
docker run -dit --link test1 --name test2 centos /bin/bash
B. 将容器加入自定义的 Docker 网络来连接多个容器
1. 新建网络
sudo docker network create -d bridge yao-bridge
-d 参数指定 Docker 网络类型,有 bridge overlay。其中 overlay 网络类型用于 Swarm mode
2. 连接容器
运行一个容器并连接到新建的 yao-bridge 网络
docker run -it --rm --name busybox1 --network yao-bridge busybox sh
打开新的终端,再运行一个容器并加入到 yao-bridge 网络
docker run -it --rm --name busybox2 --network yao-bridge busybox sh
验证连接ping
ping ip地址
ping 容器名字
在busybox1里面 ping busybox2
端口映射
存储
Docker 数据管理
数据卷(Volumes)
就是挂一个磁盘给docker containers
挂载主机目录 (Bind mounts)
指定container存储目录
为了实现数据持续化存储
Docker容器数据卷
是什么
能干什么
卷就是目录或者文件,存在于一个或者多个容器中,由docker挂载到容器,但是不属于联合文件系统,因此能绕过Union File System提供一些用于持续存储或共享数据的特性。 特性: 1、数据卷 可以在容器之间共享和重用 2、对 数据卷 的修改会立马生效 3、对 数据卷 的更新,不会影响镜像 4、数据卷 默认会一直存在,即使容器被删除
容器的持久化
容器间继承+共享数据
数据卷
容器内添加
DockerFile添加
创建一个数据卷
$ docker volume create my-vol
查看所有的 数据卷
[root@RDS-TEST-21016 my-vol]# docker volume ls DRIVER VOLUME NAME local cyy
在主机里使用以下命令可以查看指定 数据卷 的信息
数据卷 信息在 "Mounts" Key 下面
[root@RDS-TEST-21016 my-vol]# docker volume inspect cyy [ { "CreatedAt": "2019-07-17T18:18:20+08:00", "Driver": "local", "Labels": {}, "Mountpoint": "/var/lib/docker/volumes/cyy/_data", "Name": "cyy", "Options": {}, "Scope": "local" } ]
启动一个挂载数据卷的容器
1. docker run -d -P \ --name web \ # -v my-vol:/wepapp \ --mount source=my-vol,target=/webapp \ training/webapp \ python app.py
可以用 --mount source=my-vol,target=/webapp,或者用-v my-vol:/wepapp(-v 数据卷名称 容器目录 )
2. 查看数据卷是否挂载成功
docker inpect 容器containerID
3. 容器和宿主机之前数据共享
4. 容器停止退出后,主机修改后数据是否同步
5. 命令(带权限)
删除数据卷
数据卷 是被设计用来持久化数据的,它的生命周期独立于容器,Docker 不会在容器被删除后自动删除 数据卷,并且也不存在垃圾回收这样的机制来处理没有任何容器引用的 数据卷。如果需要在删除容器的同时移除数据卷。可以在删除容器的时候使用 docker rm -v 这个命令。
docker volume rm my-vol
docker volume prune
清理无主的数据卷
数据卷容器
挂载一个主机目录作为数据卷
上面的命令加载主机的 /src/webapp 目录到容器的 /opt/webapp目录。这个功能在进行测试的时候十分方便,比如用户可以放置一些程序到本地目录中,来查看容器是否正常工作。本地目录的路径必须是绝对路径,以前使用 -v 参数时如果本地目录不存在 Docker 会自动为你创建一个文件夹,现在使用 --mount 参数时如果本地目录不存在,Docker 会报错。
docker run -d -P \ --name web \ # -v /src/webapp:/opt/webapp \ --mount type=bind,source=/src/webapp,target=/opt/webapp \ training/webapp \ python app.py
Docker 挂载主机目录的默认权限是 读写,用户也可以通过增加 readonly 指定为 只读。
$ docker run -d -P \ --name web \ # -v /src/webapp:/opt/webapp:ro \ --mount type=bind,source=/src/webapp,target=/opt/webapp,readonly \ training/webapp \ python app.py
容器间传递共享(--volumes-from)
先启动一个父容器dc001
docker run -d -P --name dc001 -v /data:/dc001 centos /bin/bash
dc002/dc003继承dc001
--volumes-from
命令
docker run -d -P --name dc002 --volume-from dc001 centos /bin/bash
docker run -d -P --name dc003 --volume-from dc001 centos /bin/bash
结论:容器之间配置信息的传递,数据卷的生命周期一直执行到没有容器使用它为止
docker挂载主机目录出现:cannot open directory.:Permisson denied
解决办法:在挂载目录后面加一个--privileged=true参数即可
可以在dockerfile里面直接写挂载
如果启动的时候没有指定主机挂载volume,容器会自己生成一个,但是容器删除后,该volume也会被删除
Dockerfile
Dockerfile 是一个文本文件,其内包含了一条条的 指令(Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。
是什么
dockerfile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本
语法
在docker语法中,#表示单行注释 command argument argument... dockerfile的语法就是,命令+参数+参数+...
例
除了选择现有镜像为基础镜像外,Docker 还存在一个特殊的镜像,名为 scratch。这个镜像是虚拟的概念,并不实际存在,它表示一个空白的镜像。 FROM scratch ... 如果你以 scratch 为基础镜像的话,意味着你不以任何镜像为基础,接下来所写的指令将作为镜像第一层开始存在。 不以任何系统为基础,直接将可执行文件复制进镜像的做法并不罕见,比如 swarm、coreos/etcd。对于 Linux 下静态编译的程序来说,并不需要有操作系统提供运行时支持,所需的一切库都已经在可执行文件里了,因此直接 FROM scratch 会让镜像体积更加小巧。使用 Go 语言 开发的应用很多会使用这种方式来制作镜像,这也是为什么有人认为 Go 是特别适合容器微服务架构的语言的原因之一。
构建三步骤
dockerfile---->docker build---->docker run
文件什么样
touch Dockerfile
使用 Dockerfile 定制镜像流程
1. 手动编写一个dockerfile文件,符合dockerfile的规范
2. 有了dockerfile文件后,直接docker build命令执行,获得一个自定义的镜像
1. 在 Dockerfile 文件所在目录执行:
docker build -t 新镜像名字:TAG .
2. 不在Dockerfile文件目录
docker build -f Dockfile路径 -t 新镜像名字:TAG .
3. docker run
Dockerfile构建过程解析
Dockerfile内容基础知识
1. 每条保留字指令都必须为大写字母且后面要至少跟随一个参数
2. 指令按照从上到下,顺序执行
3. #表示注释
4. 每条指令都会创建一个新的镜像层,并对镜像进行提交
Docker执行dockerfile的大致流程
a. docker从基础镜像运行一个容器
b. 执行一条指令并对容器作出修改
c. 执行类型docker commit的操作提交一个新的镜像层
d. docker再基于刚提交的镜像运行一个新容器
e. 执行dockerfile中的下一条指令直到所有指令都执行完成
小总结
Dockerfile体系结构
Union FS 是有最大层数限制的,比如 AUFS,曾经是最大不得超过 42 层,现在是不得超过 127 层。
FROM
声明基础镜像,说明当前新镜像是基于哪一个镜像的
MAINTAINER
镜像的作者和邮箱
RUN
格式
exec 格式:RUN ["可执行文件", "参数1", "参数2"]
shell 格式:RUN <命令>,就像直接在命令行中输入的命令一样。
容器构建时需要执行的命令
例
FROM debian:stretch RUN apt-get update RUN apt-get install -y gcc libc6-dev make wget RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" RUN mkdir -p /usr/src/redis RUN tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 RUN make -C /usr/src/redis RUN make -C /usr/src/redis install
由于Union FS的最大层数限制
优化写法: FROM debian:stretch RUN buildDeps='gcc libc6-dev make wget' \ && apt-get update \ && apt-get install -y $buildDeps \ && wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \ && mkdir -p /usr/src/redis \ && tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \ && make -C /usr/src/redis \ && make -C /usr/src/redis install \ && rm -rf /var/lib/apt/lists/* \ && rm redis.tar.gz \ && rm -r /usr/src/redis \ && apt-get purge -y --auto-remove $buildDeps
EXPOSE
格式为 EXPOSE <端口1> [<端口2>...]
声明运行时容器提供服务端口
EXPOSE 指令是声明运行时容器提供服务端口,这只是一个声明,在运行时并不会因为这个声明应用就会开启这个端口的服务。在 Dockerfile 中写入这样的声明有两个好处,一个是帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射;另一个用处则是在运行时使用随机端口映射时,也就是 docker run -P时,会自动随机映射 EXPOSE 的端口。 要将 EXPOSE 和在运行时使用 -p <宿主端口>:<容器端口> 区分开来。-p,是映射宿主端口和容器端口,换句话说,就是将容器的对应端口服务公开给外界访问,而 EXPOSE 仅仅是声明容器打算使用什么端口而已,并不会自动在宿主进行端口映射。
WORKDIR
格式为 WORKDIR <工作目录路径>
指定工作目录(或者称为当前目录),以后各层的当前目录就被改为指定的目录,如该目录不存在,WORKDIR 会帮你建立目录。
ENV
格式有两种: ENV <key> <value> ENV <key1>=<value1> <key2>=<value2>...
这个指令很简单,就是设置环境变量而已,无论是后面的其它指令,如 RUN,还是运行时的应用,都可以直接使用这里定义的环境变量。
COPY
格式: COPY [--chown=<user>:<group>] <源路径>... <目标路径> COPY [--chown=<user>:<group>] ["<源路径1>",... "<目标路径>"]
类型ADD,拷贝文件和目录到镜像中。 将从构建上下文目录中<源路径>文件/目录复制到新的一层的镜像内的<目前路径>路径
ADD
ADD 指令和 COPY 的格式和性质基本一致。COPY命令的升级,它可以复制并且解压缩
VOLUME
之前我们说过,容器运行时应该尽量保持容器存储层不发生写操作,对于数据库类需要保存动态数据的应用,其数据库文件应该保存于卷(volume)中,后面的章节我们会进一步介绍 Docker 卷的概念。为了防止运行时用户忘记将动态文件所保存目录挂载为卷,在 Dockerfile 中,我们可以事先指定某些目录挂载为匿名卷,这样在运行时如果用户不指定挂载,其应用也可以正常运行,不会向容器存储层写入大量数据。 VOLUME /data 这里的 /data 目录就会在运行时自动挂载为匿名卷,任何向 /data 中写入的信息都不会记录进容器存储层,从而保证了容器存储层的无状态化。当然,运行时可以覆盖这个挂载设置。比如: docker run -d -v mydata:/data xxxx 在这行命令中,就使用了 mydata 这个命名卷挂载到了 /data 这个位置,替代了 Dockerfile 中定义的匿名卷的挂载配置。
格式为: VOLUME ["<路径1>", "<路径2>"...] VOLUME <路径>
容器数据卷,用于数据保存和持久化工作
CMD
CMD 指令的格式和 RUN 相似,也是两种格式: shell 格式:CMD <命令> exec 格式:CMD ["可执行文件", "参数1", "参数2"...] 参数列表格式:CMD ["参数1", "参数2"...]。在指定了 ENTRYPOINT 指令后,用 CMD 指定具体的参数。
指定一个容器启动时要运行的命令
Dockerfile中可以有多个CMD指令,但只有最后一个生效,CMD会被docker run之后的参数替换
ENTRYPOINT
指定一个容器启动时要运行的命令
EBTRYPOINT的目的和CMD一样,都是在指定容器启动程序及参数
ONBUILD
当构建一个被继承的Dockerfile时运行命令,父镜像在被子继承后父镜像的onbuild被触发
小总结
总结
Docker的系统资源限制
资源限制原理
docker容器默认是没有资源限制的
docker底层是通过cgroup来管理资源的
cat /proc/cgroups
当前docker仅使用了上述子系统列表中的七种,blkio、cpu、cpuacct、cpuset、device、freezer和memory。啊用户可通过Docker create命令或者Docker run命令来设置上面这些参数的数值。本质上来说,就是Docker Daemon将次容器所有的进程都添加到一个group中,然后这个group关联其他层级树。
从内核角度来看,cgroups就是内核在内核态进程中设置的钩子函数。当用户态任务运行过程中需要申请某项资源的时,就会触发相应的子系统钩子函数进行检测,最终根据资源类别的不同,使用相应的技术,进行资源限制和优先级分配
具体做法
Docker只需对cgroup文件系统中的各个文件进行修改,就可以达到对指定容器的资源管理,而操作的文件路径为/sys/fs/cgroup
在运行容器的时候可以加相关参数,如-cpu \-m等
部分资源限制操作
cpu
可选参数
[root@RDS-TEST-21016 ~]# docker run --help | grep cpu --cpu-period int Limit CPU CFS (Completely Fair Scheduler) period --cpu-quota int Limit CPU CFS (Completely Fair Scheduler) quota --cpu-rt-period int Limit CPU real-time period in microseconds --cpu-rt-runtime int Limit CPU real-time runtime in microseconds -c, --cpu-shares int CPU shares (relative weight) --cpus decimal Number of CPUs --cpuset-cpus string CPUs in which to allow execution (0-3, 0,1) --cpuset-mems string MEMs in which to allow execution (0-3, 0,1)
常用
-c, --cpu-shares int 可以设置多个容器使用cpu,按照比例来
CPU shares (relative weight) 在创建容器时挃定容器所使用的 CPU 份额 值。 cpu-shares的值丌能保证可以获得 1个vcpu 戒者多少GHz的 CPU资源,仅仅只是一个弹性的加 权值。 默认情况下,每个 docker容器的cpu 份额都是 1024。单独一个容器的份额是没有意义的,只有在 同时运行多个容器时,容器的 cpu加权的效果才能体现出来
例:给容器实例分配 512权重的 cpu使用份额 参数: --cpu-shares 512 [root@xuegod63 ~]# docker run -it --cpu-shares 512 centos /bin/bash [root@df176dd75bd4 /]# cat /sys/fs/cgroup/cpu/cpu.shares #查看结果: 512
默认情况下,每个 docker容器的cpu 份额都是 1024。单独一个容器的份额是没有意义的,只有在 同时运行多个容器时,容器的 cpu加权的效果才能体现出来。
例: 两个容器 A、B的cpu 份额分别为 1000和500,结果会怎么样? | 情况1:A和B 正常运行,在cpu迚行时间片分配的时候,容器A比容器 B 多一倍的机会获得 CPU 的时间片。 情况2:分配的结果叏决于当时主机和其他容器的运行状态,实际上也无法保证容器A一定能获得CPU 时间片。比如容器A的迚程一直是空闲的,那么容器B是可以获叏比容器 A更多的 CPU时间片的。极端 情况下,比如说主机上只运行了一个容器,即使它的 cpu份额只有50,它也可以独占整个主机的 cpu资 源。 问:两个容器 A、B的cpu份额分别为1000和500, 1000+500> 1024 是超出了吗? 答:没有。A使用 1024的2/3 ,B 使用 1024的1/3
--cpuset-cpus 可以绑定使用哪一个CPU
对多核 CPU 的服务器,docker 还可以控制容器运行限定使用哪些 cpu 内核和内存节点,即使用– cpuset-cpus和–cpuset-mems参数。对具有NUMA拓扑(具有多 CPU、多内存节点)的服务器尤其 有用,可以对需要高性能计算的容器迚行性能最优的配置。
例:物理机一共有 16个核心,创建的容器只能用 0、1、2这三个核心。 [root@xuegod63 ~]# docker run -it --name cpu1 --cpuset-cpus 0-2 centos [root@ad554956e989 /]# cat /sys/fs/cgroup/cpuset/cpuset.cpus 0-2 [root@b3f567c41a1a /]# taskset -cp 1 pid 1's current affinity list: 0-2
--cpus decimal 可以设置使用cpu的个数
例:物理机一共有 16个核心,创建的容器能用8个核心。 [root@xuegod63 ~]# docker run -it --name cpu1 --cpus 8 centos
memory
可选参数
[root@RDS-TEST-21016 ~]# docker run --help | grep memory --kernel-memory bytes Kernel memory limit -m, --memory bytes Memory limit --memory-reservation bytes Memory soft limit --memory-swap bytes Swap limit equal to memory plus swap: '-1' to enable unlimited swap --memory-swappiness int Tune container memory swappiness (0 to 100) (default -1)
常用
Docker 提供参数-m, --memory=""限制容器的内存使用量
例1:允许容器使用的内存上限为 128M [root@xuegod63 ~]# docker run -it -m 128m centos 查看: [root@40bf29765691 /]# cat /sys/fs/cgroup/memory/memory.limit_in_bytes 134217728
IO
参数
[root@RDS-TEST-21016 ~]# docker run --help | grep write-b --device-write-bps list Limit write rate (bytes per second) to a device (default [])
disk
Docker+K8s+Jenkins实战
案例
Centos测试环境部署实践
1. 编写Dockerfile文件
FROM centos:centos7.5.1804 MAINTAINER chenyaoyao <942602590@qq.com> RUN yum -y install net-tools perl perl-libs unzip autoconf iproute RUN mkdir /data
2. 构建
docker build -t 新镜像名字:TAG .

3. 运行
创建一台4核8G,60GB的centos7.5机器
4. 列出镜像的变更历史
docker history 镜像名字
5. 部署RDS
一键部署
添加中间件服务器
添加数据源服务器
docker常用安装
总体步骤
1. 搜索镜像
2. 拉取镜像
3. 查看镜像
4. 启动镜像
5. 停止容器
6. 移除容器
安装mysql
docker search mysql
docker pull mysql:5.6
加上标签可以选择mysql版本
运行
docker run -p 3322:3306 --name mysql1 -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.6
进入mysql
docker exec -it f13ca4718629(容器的CONTAINER ID) /bin/bash
删除
docker container rm -f f13ca4718629
rm -f是强制删除
安装redis
运行状态图