Docker
1. docker介绍
虚拟化级别可以分为四层:
1) 完全虚拟化:处理器密集型奇数,要求hypervisor管理各个虚拟服务器。并让它们彼此独立,如Vmware/Virtual PC;
2) 准虚拟化:改动客户操作系统,让它认为自己运行在虚拟环境下,能够参与hypervisor协同工作(para-virturalization);
3) 系统虚拟化:没有独立的hypervisor层,主机操作系统本来本身就负责在多个虚拟服务器之间分配资源,并让这些服务器彼此独立;
4) 桌面虚拟化:主要工能是将分散的桌面环境集中保存并管理起来,包括桌面环境的集中下发、集中更新、集中管理。桌面虚拟化使得桌面管理变得简单,不用每台终端单独进行维护,每台终端进行更新。
docker和其他容器(container)技术都属于系统虚拟换范畴。
容器( container-based )虚拟化方案,充分利用了操作系统本身已有的机制和特性,以实现轻量级的虚拟化(每个虚拟机安装的不是完整的虚拟机),甚至有人把他称为新一代的虚拟化技术, Docker 无疑就是其中的佼佼者。在一台服务器上同时运行上百个虚拟机,肯定会被认为是痴人说梦,而在一台机器上同时运行一千个 Docker 容器,这已成为现实。
1> Docker 的目标:
Build,Ship and Run Any App,Anywhere— 即通过对应用组件的封装 (Packaging), 发布(Distribution), 运行 (runing) 等生命周期的管理 , 达到应用组件级别的“一次封装 , 到处运行”。简单的说,容器就像一个集装箱,把所需的应用服务封装到里面,使用的时候直接使用容器即可。
2> docker的特点
优点:
启动快,资源占用小 , 资源利用高,快速构建标准化运行环境;
创建分布式应用程序时快速交付和部署,更轻松的迁移和扩展,更简单的更新管理。
局限:
Docker 是基于 Linux 64bit 的,无法在 windows/unix 或 32bit 的 linux环境下使用;
LXC 是基于 cgroup 等 linux kernel 功能的,因此 container 的 guest 系统只能是linux;
隔离性相比 KVM 之类的虚拟化方案还是有些欠缺,所有 container 公用一部分的运行库;
管理相对简单,主要是基于 namespace 隔离;
cgroup 的 cpu 和 cpuset 提供的 cpu 功能相比 KVM 的等虚拟化方案相比难以度量 ( 所以 dotcloud 主要是按内存收费 );
docker 对 disk 的管理比较有限;
container 随着用户进程的停止而销毁, container 中的 log 等用户数据不便收集。
3> docker与虚拟机比较:
启动快比虚拟机 , 可以秒级启动;
对资源占用小 , 宿主机上可运行千台容器;
方便用户获取 , 分布 , 和更新应用镜像 , 指令简单 , 学习费用低;
通过 Dockerfile 配置文件来灵活的自动创建和部署镜像 & 容器 , 提高工作效率;
Docker 除了运行其中应用外 , 基本不消耗其他系统资源 , 保证应用性能同时 , 尽量减小系统开销。
4> docker相关网站
官方镜像:https://hub.docker.com/
官方手册:https://docs.docker.com/
中文手册:http://docs.docker-cn.com
2. docker容器的安装
部署好源后直接使用 yum install docker -y 安装即可。也可以安装其二级制文件包。此处使用内网文件二进制包进行安装。
1> 解析内网,下载安装二进制文件
[root@alph ~]# vim /etc/resolv.conf # Generated by NetworkManager nameserver 172.16.254.110 #内网解析 [root@alph ~]# wget http://download2.yunwei.edu/shell/docker.tar.gz #下载二进制包 [root@alph ~]# ls docker.tar.gz [root@alph ~]# tar zxf docker.tar.gz [root@alph ~]# ls docker docker.tar.gz [root@alph docker]# ls ca.crt docker-app.tar.gz docker.sh remove.sh #二进制文件 [root@alph docker]# vim docker.sh #脚本内容 #/bin/bash tar zxvf docker-app.tar.gz -C /usr/local/bin/ #解压缩至 mkdir -p /etc/docker mkdir -p /etc/docker/certs.d/reg.yunwei.edu #自己配置文件目录 cp ca.crt /etc/docker/certs.d/reg.yunwei.edu/ #copy crt证书文件 echo "172.16.254.20 reg.yunwei.edu">>/etc/hosts cat <<EOF>/etc/docker/daemon.json #指定容器的镜像仓库 { "registry-mirrors": ["http://cc83932c.m.daocloud.io"], "max-concurrent-downloads": 10, "log-driver": "json-file", "log-level": "warn", "log-opts": { } } EOF cat <<EOF>/etc/systemd/system/docker.service #docker的启动文件 [Unit] Description=Docker Application Container Engine Documentation=http://docs.docker.io
[Service] Environment="PATH=/usr/local/bin:/bin:/sbin:/usr/bin:/usr/sbin" ExecStart=/usr/local/bin/dockerd ExecStartPost=/sbin/iptables -I FORWARD -s 0.0.0.0/0 -j ACCEPT ExecReload=/bin/kill -s HUP $MAINPID Restart=on-failure RestartSec=5 LimitNOFILE=infinity LimitNPROC=infinity LimitCORE=infinity Delegate=yes KillMode=process [Install] WantedBy=multi-user.target EOF systemctl daemon-reload && systemctl enable docker.service && systemctl start do #重新加载并启动docker cker.service [root@alph docker]# bash docker.sh #执行脚本,安装二进制包 ocker docker-compose docker-containerd docker-containerd-ctr docker-containerd-shim dockerd docker-init docker-proxy docker-runc Created symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /etc/systemd/system/docker.service. [root@alph docker]# cd /usr/local/bin/ #docker存放位置 [root@alph bin]# ls docker docker-containerd-ctr docker-init docker-compose docker-containerd-shim docker-proxy docker-containerd dockerd docker-runc [root@alph docker]# systemctl status docker #查看状态 ..... Active: active (running) since Thu 2019-07-11 22:49:37 CST; 9min ago [root@alph docker]# docker --version #利用docker自己的命令查看版本 Docker version 18.03.0-ce, build 0520e24 #免费版(ce)18.03.0 [root@alph docker]# docker ps #查看docker启动的容器 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3. docker镜像
查看本地的镜像
[root@alph docker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
#镜像池(地址) 镜像版本 镜像id 镜像创建时间 镜像大小
1> 镜像下载
格式: docker pull 镜像名称
进入docker镜像官网,搜索所需镜像,然后点击镜像。进去后会有相应的命令提示,再执行相应的命令即可。
[root@alph docker]# docker pull busybox [root@alph docker]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE busybox latest e4db68de4ff2 3 weeks ago 1.22MB
对于docker自己的镜像官网下载的镜像,其镜像池只有镜像的名字,而对于其他的网站下载的镜像,镜像池显示的是下载地址及镜像名。
2> 镜像的删除
格式: docker rmi ID
[root@alph docker]# docker rmi e4db68de4ff2
[root@alph docker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
3> 镜像重命名(别名)
格式:docker tag 原名:版本 新名:新版本(可以不指定)
[root@alph docker]# docker tag busybox:latest newbusybox:v1 [root@alph docker]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE busybox latest e4db68de4ff2 3 weeks ago 1.22MB newbusybox v1 e4db68de4ff2 3 weeks ago 1.22MB
删除别名(不会删除原来的镜像):
格式:docker rmi 别名:版本号
[root@alph docker]# docker rmi newbusybox:v1 Untagged: newbusybox:v1 [root@alph docker]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE busybox latest e4db68de4ff2 3 weeks ago 1.22MB
4> 在命令行搜索镜像下载
格式:docker search 名称,再进行pull下载
[root@alph docker]# docker search mariadb NAME DESCRIPTION STARS OFFICIAL AUTOMATED mariadb MariaDB is a community-developed fork of MyS… 2872 [OK] bitnami/mariadb Bitnami MariaDB Docker Image 102 ......... [root@alph docker]# docker pull mariadb/server
4. docker镜像分层
docker镜像的分层结构:支持通过扩展现有镜像,创建新的镜像。
可以看到,新镜像是从 base 镜像一层一层叠加生成的。每安装一个软件,就在现有镜像的基础上增加一层,在新增的镜像里安装软件。
1> 分层结构的优势
共享资源:
有多个镜像都从相同的 base 镜像构建而来,那么 Docker Host 只需在磁盘上保存一份 base 镜像;同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享,我们将在后面更深入地讨论这个特性。
如果多个容器共享一份基础镜像,当某个容器修改了基础镜像的内容,比如 /etc 下的文件,其他容器的 /etc 是否不会被修改。修改会被限制在单个容器内。这就是容器 Copy-on-Write 特性。
可写的容器层:
当容器启动时,一个新的可写层被加载到镜像的顶部。这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。所有对容器的改动 - 无论添加、删除、还是修改文件都只会发生在容器层中。只有容器层是可写的,容器层下面的所有镜像层都是只读的。
镜像层数量可能会很多,所有镜像层会联合在一起组成一个统一的文件系统。如果不同层中有一个相同路径的文件,比如 /a,上层的 /a 会覆盖下层的 /a,也就是说用户只能访问到上层中的文件 /a。在容器层中,用户看到的是一个叠加之后的文件系统。
2> 添加文件
在容器中创建文件时,新文件被添加到容器层中。
3> 读取文件
在容器中读取某个文件时,Docker 会从上往下依次在各镜像层中查找此文件。一旦找到,打开并读入内存。
4> 修改文件
在容器中修改已存在的文件时,Docker 会从上往下依次在各镜像层中查找此文件。一旦找到,立即将其复制到容器层,然后修改之。
5> 删除文件
在容器中删除文件时,Docker 也是从上往下依次在镜像层中查找此文件。找到后,会在容器层中记录下此删除操作。
只有当需要修改时才复制一份数据,这种特性被称作 Copy-on-Write。可见,容器层保存的是镜像变化的部分,不会对镜像本身进行任何修改。容器层记录对镜像的修改,所有镜像层都是只读的,不会被容器修改,所以镜像可以被多个容器共享。
5. 镜像的创建
创建镜像的三种方法
(1)基于修改后的容器创建:docker commit 命令
(2)基于本地模板导入
(3)基于 Dockerfile 文件创建
1> 基于修改后的容器创建
格式:docker run -it 镜像:版本 /bin/sh(环境变量)
[root@alph docker]# docker run -it busybox:latest /bin/sh / # #进入容器 / # cd /root ~ # pwd /root ~ # echo "hello docker" > welcome #在该容器写入测试文件 ~ # ls welcome ~ # cat welcome hello docker ~ # exit
生成新的镜像
格式:docker commit 容器名(或者id) 镜像名:版本(可以重新命名)
[root@alph docker]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES a05504bbd249 busybox:latest "/bin/sh" 17 minutes ago Exited (0) 12 minutes ago ecstatic_keldysh [root@alph docker]# docker commit a05504bbd249 busybox:1 #生成镜像 sha256:039a9254f08586a9954718e98062fcf8deb1032f287ee1bb4e6cde0f4b7867e5 [root@alph docker]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE busybox 1 039a9254f085 39 seconds ago 1.22MB busybox latest e4db68de4ff2 3 weeks ag
进入创建的镜像,查看镜像内容。该镜像是基于现有的容器创建的,因此含有容器的内容。
[root@alph docker]# docker run -it --name test busybox:1 /bin/sh / # cd /root ~ # ls welcome ~ # cat welcome hello docker ~ # exit
删除容器
格式: docker rm id
可以使用for循环删除所有未运行的容器
[root@alph docker]# for id in `docker ps -a | grep Exited | awk '{print $1}'`;do docker rm $id;done c9706b4a063e a05504bbd249 [root@alph docker]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2> 基于模板导入导出的镜像
导出:将镜像保存为本地文件
格式:docker save -o 导出的压缩包名 镜像名:版本
拉取的镜像名可以是ID,但建议使用镜像名,使用id导出后再导入时没有名字。
[root@alph ~]# docker save -o busybox.tar.gz busybox:1 [root@alph ~]# ls anaconda-ks.cfg busybox.tar.gz docker docker.tar.gz yum-repo.sh
导入:将压缩包文件导入到本地镜像列表
格式:docker load -i 压缩包名
[root@alph ~]# docker rmi 039a9254f085 #先删除该镜像,再导入查看 [root@alph ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE busybox latest e4db68de4ff2 3 weeks ago 1.22MB [root@alph ~]# docker load -i busybox.tar.gz 5f3c3c26311b: Loading layer 3.584kB/3.584kB Loaded image: busybox:1 [root@alph ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE busybox 1 039a9254f085 2 hours ago 1.22MB busybox latest e4db68de4ff2 3 weeks ago 1.22MB
也可以将导出的镜像文件共享给其他节点,其他节点导入即可使用。
简单来说,容器是镜像的运行实体。所不同的是它带有额外的可写层。
3> 基于dockerfile文件创建镜像
Dockerfile 是一个文本文件,用来配置 image,记录了镜像构建的所有步骤。Docker 根据 该文件生成二进制的 image 文件。
使用新的镜像是没有vim等命令的,现在以下载安装vim为例说明dockerfile的使用 [root@alph ~]# docker run -it busybox:1 /bin/sh / # cd /root ~ # vim a /bin/sh: vim: not found ~ #exit 新建目录用于创建dockerfile [root@alph ~]# pwd /root [root@alph ~]# mkdir doc_file [root@alph ~]# cd doc_file/ 新建dockerfile文件,文件名必须为dockerfile [root@alph doc_file]# vim dockerfile FROM busybox:1 #创建的该镜像来源于镜像busybox RUN yum install vim -y #运行下载vim
创建镜像
格式:docker build -t 镜像名:版本 镜像来源路径
[root@alph doc_file]# docker build -t test_im:1 /root/doc_file
创建完镜像后再用docker images命令查看镜像,然后再于该新建的镜像起一个容器,在使用vim命令,此时vim可以用了。
[root@alph ~]# docker run -t --name container test_im:latest /bin/sh #容器名字为container
详解参考:
查看docker的日志
格式:docker logs -f id
[root@alph ~]# docker logs -f 0e04254519e3
若容器状态不正常,先查看日志文件
退出容器用命令exit,执行命令exit后容器就停止运行了,若想退出容器后容器继续运行,使用快捷键Ctrl+Q+P。
当容器在运行时是无法用命令docker rm id 进行删除的,首先应该停止该容器:docker stop id,再进行删除。
相应的,启动和重启容器用命令start和restart。
dockerfile常用的命令(详情参考官方文档)
FROM:指定 base 镜像。
MAINTAINER:设置镜像的作者,可以是任意字符串。
COPY:将文件从 build context 复制到镜像。
COPY 支持两种形式:
COPY src dest
COPY ["src", "dest"]
注意:src 只能指定 build context 中的文件或目录。
ADD:与 COPY 类似,从 build context 复制文件到镜像。不同的是,如果 src 是归档文件(tar, zip, tgz, xz 等),文件会被自动解压到 dest。
ENV:设置环境变量,环境变量可被后面的指令使用。例如:
ENV MY_VERSION 1.3
RUN apt-get install -y mypackage=$MY_VERSION
EXPOSE:指定容器中的进程会监听某个端口,Docker 可以将该端口暴露出来。我们会在容器网络部分详细讨论。
VOLUME:将文件或目录声明为 volume。
WORKDIR:为后面的 RUN, CMD, ENTRYPOINT, ADD 或 COPY 指令设置镜像中的当前工作目录。
RUN:在容器中运行指定的命令,RUN 指令通常用于安装应用和软件包。
CMD:容器启动时运行指定的命令。
Dockerfile 中可以有多个 CMD 指令,但只有最后一个生效。CMD 可以被 docker run 之后的参数替换。
ENTRYPOINT:设置容器启动时运行的命令,可让容器以应用程序或者服务的形式运行。
Dockerfile 中可以有多个 ENTRYPOINT 指令,但只有最后一个生效。CMD 或 docker run 之后的参数会被当做参数传递给 ENTRYPOINT。
一个完整的dockerfile示例:
构建镜像过程:
运行一个容器: