最近给部门同事培训docker相关的东西,把我的培训内容总结下,发到博客园上,和大家一起分享。我的培训思路是这样的
首先讲解docker的安装、然后讲下docker的基本的原理,最后讲下docker的使用,基本上读完这篇博客大家一定可以基本上掌握docker了;其实我的想法是这样的,docker就是一个工具,我们把docker的使用搞定后,对底层原理大概了解一二就可以了,没有必要深究,下面进入正题
一、docker的安装
1、替换yum源和docker源
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.163.com/.help/CentOS7-Base-163.repo |
wget http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
|
2、清空yum缓存和重新生成缓存
yum clean all yum makecache
|
3、通过yum的方式安装docker-ce
yum install docker-ce-20.10.6 -y |
4、编写docker开机自启动脚本
[root@mylinux init.d]# pwd /etc/init.d [root@mylinux init.d]# cat startdocker.sh #! /bin/bash #chkconfig: 345 88 14
#decription:startdocker /usr/bin/systemctl start docker
|
5、设置开机自自动
[root@mylinux init.d]# pwd /etc/init.d [root@mylinux init.d]# chkconfig --add startdocker.sh [root@mylinux init.d]# chkconfig startdocker.sh on
|
6、设置linux的内核流量转发
touch /etc/sysctl.d/docker.conf |
文件内容如下
[root@mylinux ~]# cat /etc/sysctl.d/docker.conf net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 net.ipv4.conf.default.rp_filter = 0 net.ipv4.conf.all.rp_filter = 0 net.ipv4.ip_forward = 1
|
设置该修改生效
modprobe br_netfilter sysctl -p /etc/sysctl.d/docker.conf |
7、启动docker即可,至此docker安装完成
二、docker的原理和概念讲解
1、虚拟机的弊端?
之前的虚拟化都是通过虚拟一个完整的虚拟机的方式,每个独立的计算机的拥有独立的底层物理硬件,操作系统和应用程序执行的完整的环境;就比如我们公司的虚拟化平台,就是通过kvm+qemu的开源的方式提供整套虚拟机的解决方案
qumu 主要用来工作在用户空间,他本身支持所有的硬件设备的模拟,包括cpu和内存、磁盘、网卡、显卡等,欺骗guestOS的认为自己直接在和硬件打交道,其实guestOS
是在和qemu模拟出来的硬件打交道,qemu会把guestOS的指令翻译后给真正的硬件进行操作,通过这种方式,guestOS可以直接和host的硬件设备做交互,但是由于所有
的guestOS的指令都需要通过qumu的翻译,因此性能会比较差
kvm实际是由linux内核提供的虚拟化架构,kvm本身需要处理器本身支持虚拟化技术,比如inter-vt和amd-v技术,在linux2.6内核后,kvm已经合入主干中
kvm 本身不实现任何模拟,他提供一个/dev/kvm的接口,这个接口可以被host主机用来创建vcpu和运行,vcpu的寄存器的读写、虚拟内存的创建和分配。有了
kvm后,guestOS的cpu指令就不需要经过QEMU来翻译变可以直接运行,大大提高了运行速度,但是kvm本身只支持cpu和内存的虚拟化,所有他必须要结合qume
才能构成一个完整的虚拟化方案
所以为了让虚拟机中的程序实现像在真实物理机上运行的近似效果,不仅仅会带来极大的资源浪费,一个宿主机可能只能运行几个虚拟机,同时虚拟机对cpu还有特殊要求;另外虚拟机动辄十几G,管理和备份起来就非常困难;
所以容器技术的作为一个虚拟化另外一个解决方案,代替虚拟机成为新的趋势;
我们今天讲的docker其实是一个容器技术的一个最流行的解决方案;
2、容器的优势
docker是用goland语言开发的,基于linux内核的Cgroup。Namespace以及unionFS等技术,对进程进行封装隔离,属于操作系统层面的虚拟化技术
a、容器是一个轻量级的隔离系统,可以更高效的利用硬件资源,同样一个宿主机,最多可以跑几个虚拟机,但是可以跑上百个容器
b、kvm虚拟化需要硬件cpu虚拟化的支持,而容器根本就不需要
c、容器所占用的空间相比虚拟机非常小,更容易管理和备份
容器内的应用程序是直接运行在宿主机的内核上的,能够使用宿主机的最大的硬件资源,容器内没有自己的内核,也没有对硬件进行虚拟,因此容器比虚拟机更加轻便,docker引擎容器仅包含应用及其依赖,
他在主机操作系统的用户空间作为一个独立的进程运行,与其他容器共享内核,因此,他得到了虚拟机的资源隔离和分配好处,更方便和高效
3、docker平台组成
docker客户端主要为我们提供操作容器和镜像的入口
docker服务端主要是为我们管理容器和镜像
dockerhub就和gitlab一样,为我们在云端管理镜像,我们可以通过dockerhub上传、下载镜像
4、docker引擎的构成
Docker引擎是C/S架构的
5、 images(镜像)
镜像是一个只读模板,用于创建容器,也可以通过dockerfile文本描述镜像的内容创建容器,也可以直接dockerhub上拉取镜像;
镜像的概念类似于编程开发中的面向对象的类,而容器就是这个类的示例
构建容器的过程,就是运行镜像,生成容器的实例
镜像的分层架构
bootfs主要包括bootloader和kernel,bootloader主要是引导加载kernel,linux刚启动时会加载bootfs文件系统
baseimage,在bootfs之上,包含的就是典型的linux系统中的/dev ,/bin、等标准目录和文件系统的rootfs,也就是我们常说的各种不同操作系统的发行版,比如ubuntu,Centos等发行版
当通过一个image启动一个镜像,docker会在该images最顶层,添加一个读写文件系统作为容器,然后运行该容器
docker容器的本质是基于UnionFS管理的分层文件系统;
我们查看docker镜像,为什么一个linux发行版只有几百兆?因为docker镜像只有rootfs和其他镜像层,不包括宿主机的内核文件系统,因此很小。
那为什么我们查看一个nginx镜像,需要一百多兆,但是一个nginx其实只有几kb?因为docker镜像是分层,nginx的确很小,但是一个用于运行nginx的镜像文件,依赖父镜像就比较大大了。
6、container(容器)
容器是一个镜像运行的实例
创建容器的的过程
a、获取镜像,如docker pull centos从镜像仓库拉取,或者自己通过dockerfile创建
b、使用run命令启动一个容器
c、分配文件系统,挂载一个读写层,在读写层加载镜像
d、分配网络和网桥接口,创建一个网络接口,让容器和宿主机通信
e、容器获取ip地址
f、执行容器的命令,如/bin/bash
g、返回容器启动结果
7、dockerhub(镜像仓库)
docker的镜像需要管理,docker提供了Registry仓库,其实他也是一个容器,
8、dockerfile
将创建镜像写成一个脚本,docker build命令就会执行dockerfile中的指令来创建镜像
dockerfile镜像的描述文件,包含以下指令,后面我们重点讲解,这里简单了解即可
FROM 定义基础镜像
MAINTAINER 作者
RUN 运行linux命令
ADD 添加文件/目录
ENV 设置环境变量
CMD 运行镜像要执行命令
三、docker命令讲解
1、平台相关命令
查看docker版本
docker --version
查看docker服务状态
systemctl status docker #查看docker服务状态 systemctl stop docker #关闭docker服务 systemctl start docker #启动docker服务 systemctl restart docker #重启docker服务
docker info |grep Root #查看docker的镜像存储位置
2、docker镜像相关命令
搜索镜像
docker search centos
从dockerhub拉取镜像
docker pull centos
查看本地的docker镜像
docker images
查看本地镜像,只显示镜像ID
docker images -q
删除本地镜像,可以通过名称删除,也可以通过镜像id删除
docker rmi centos
查看镜像相关信息
docker image inspect 5d0da3dc9764
3、Dockerfile相关命令:如果你想自定义镜像内容,就需要自己写脚本,这里的脚本也就是Dcokerfile
定制镜像其实有两种方法
1、手工修改容器的内容,然后导出容器为镜像
2、基于dockerfile自行编写指令,基于指令流程创建镜像
下面介绍下Dockerfile中的常见指令
FROM 基础镜像信息,提供rootfs的功能
MAINTAINER 镜像的作者信息,可以不写
RUN 制作镜像的指令,也就是在docker内执行的linux的命令,每个RUN 就相当于一层镜像,所以尽量把命令写在一个RUN中,不然镜像就会很大
ADD 拷贝宿主机本地的文件到镜像内
COPY 拷贝宿主机的本地的文件到镜像内容,如果tar.gz\zip\xz类型的会自动解压,这也是COPY指令和ADD的区别
WORKDIR 类似于linux中的cd命令,切换工作目录
USER 用于改变用户,和linxu中的切换用户的功能是一样的
VOLUME 这里可以指定一个镜像内部的目录,docker会把这个目录挂载到宿主机的某个目录下,这个后面我们查看镜像信息就可以看到他挂载的宿主机的哪个目录了
容器运行的时候,应该保证存储层不要写入任何数据,运行容器生成的数据,我们推荐是挂载的方式,写入到宿主机上,进行维护
EXPOSE 设置镜像对外打开的端口
ENV 设置环境变量,通过ENV设置的环境变量在镜像启动为容器后继续生效
ARG 设置环境变量,通过ARG设置的环境变量在镜像启动为容器后就不在生效
CMD 指定容器启动后要干的事情
下面看一个Dockerfile的例子
FROM centos MAINTAINER hellodocker RUN echo "this is my first docker images" RUN mkdir /data VOLUME /data ADD abc.txt /data COPY abc.tar.gz /data ENV name = "hello world" ARG add RUN echo ${name} ARG age="12" RUN echo ${age} WORKDIR /data CMD ["/bin/bash"]
这里要注意这个问题
a、通过add、copy命令拷贝的文件要在和dockerfile相同的目录下
b、利用arg定义的命令,key和value之间的等号要没有空格,不然会跑错
c、另外使用arg参数可以接受build传的参数
比如我们在docker这样写
在构建的时候就需要这样构建
下面就是我们构建的过程
[root@mylinux docker]# docker build --build-arg add="sz" ./ Sending build context to Docker daemon 6.144kB Step 1/14 : FROM centos ---> 5d0da3dc9764 Step 2/14 : MAINTAINER hellodocker ---> Running in 71362c2a7dd5 Removing intermediate container 71362c2a7dd5 ---> d18802a8f3b0 Step 3/14 : RUN echo "this is my first docker images" ---> Running in 6d7e2fe3f3ec this is my first docker images Removing intermediate container 6d7e2fe3f3ec ---> 6fe7890d4db3 Step 4/14 : RUN mkdir /data ---> Running in 4fe2cb44c769 Removing intermediate container 4fe2cb44c769 ---> 5625a2c2d32f Step 5/14 : VOLUME /data ---> Running in 566bcc7901ae Removing intermediate container 566bcc7901ae ---> a5fb2e009365 Step 6/14 : ADD abc.txt /data ---> 9fff6fff0e03 Step 7/14 : COPY abc.tar.gz /data ---> 6305fe28d70c Step 8/14 : ENV name = "hello world" ---> Running in 19894058bf3d Removing intermediate container 19894058bf3d ---> b8cef325887e Step 9/14 : ARG add ---> Running in ca3b757fd0f8 Removing intermediate container ca3b757fd0f8 ---> 974e2b0586fa Step 10/14 : RUN echo ${name} ---> Running in 3d2e2b5d8d2e = hello world Removing intermediate container 3d2e2b5d8d2e ---> 1a6805e71aca Step 11/14 : ARG age="12" ---> Running in b4002f463007 Removing intermediate container b4002f463007 ---> 4c6b01d13609 Step 12/14 : RUN echo ${age} ---> Running in b98d429ba25f 12 Removing intermediate container b98d429ba25f ---> 8c72f6092704 Step 13/14 : WORKDIR /data ---> Running in a88092bf35f7 Removing intermediate container a88092bf35f7 ---> b3ca82aa4440 Step 14/14 : CMD ["bin","bash"] ---> Running in 9003133696dc Removing intermediate container 9003133696dc ---> 47afe19c79df Successfully built 47afe19c79df
此时如果我们docker images查看docker镜像,这个镜像是没有名称的
我们可以在构建的时候加个tag字段知名
[root@mylinux docker]# docker build --build-arg add="sz" --tag "firstimage" ./
此时在查看我们的镜像
4、容器相关的命令
上面我们已经构建了一个镜像,下面我们就基于这个镜像进行容器相关的命令学习
docker ps
docker ps #查看当前启动的容器 docker ps -a #查看曾经启动过的容器
docker rm 容器ID
docker rm 389de141edf2 #删除容器的启动记录
docker run -it myimage
docker run -it 镜像名称 #前台运行镜像,并分配一个终端
docker container inspect 72dacd386293
docker container inspect 72dacd386293 #查看容器的相关属性信息
docker run -it myimage ping www.baidu.com
docker run -it myimage ping www.baidu.com #启动容器,并在容器内执行对应命令
docker run -d myimage
docker run -d myimage #后台启动容器
我们通过宿主机的linux命令可以看到容器的ip地址
docker top 640a0ba6125b
docker top 640a0ba6125b #同linux后台top命令
docker exec -it 640a0ba6125b ip a
docker exec -it 640a0ba6125b ip a #进入一个启动的容器,并执行相关命令
启动还有其他参数 -p 端口映射
宿主机的9000会映射到容器的900端口
可以查看转发情况
docker run -d --name mycontainer myimage ping www.baidu.com
docker run -d --name mycontainer myimage ping www.baidu.com # --name 为容器起一个名字
docker logs 容器id
docker logs ddaa72f7a52f #查看容器的输出的日志
docker stop 容器id
docker stop #关闭一个容器
可以测试下我们Dockerfile中定义的变量
测试下我们创建的目录
测试我们挂载的目录
我们先通过docker container inspect 容器id查看宿主机的挂载的目录
docker commit
docker commit -a docertest -m "test commit" a068fbd45560 testdocker:v1.0.0 -a :提交的镜像作者; -m :提交时的说明文字;
docker save
docker save testdocker:v1.0.0 > /data/docker/testdocker.tar 把镜像文件转换为本地文件,进行保存和管理
docker load -i
docker load -i testdocker.tar #把本地的镜像文件变为镜像
至此,我觉得大家看我的博客,基本上可以满足日常的工作需要,有需要的朋友可以博客交流,谢谢大家!