为了能很好的了解k8s,这里小编写大致的将docker的基础做一些介绍,这里小编将会以2篇博文的形式,详细的介绍一下docker的基础部分,这一篇是docker的概念以及docker的基本使用,后续会在发布一篇关于docker的官网上的quick-start的实战案例,让大家能更好的了解docker。
一、docker的介绍
1.什么是docker?
Docker是一个开源的引擎,可以轻松的为任何应用创建一个轻量级的、可移植的、自给自足的容器。开发者在笔记本上编译测试通过的容器可以批量地在生产环境中部署,包括VMs(虚拟机)、bare metal、OpenStack 集群和其他的基础应用平台。
2.docker的优点
Docker通过容器来打包应用,意味着迁移只需要在新的服务器上启动需要的容器就可以,降低部署过程出现的问题的风险。
更高的资源利用,docker容器的运行不需要额外的虚拟化管理程序支持,它是内核级的虚拟化,可以实现更高的性能。
更轻松的更新管理。使用dockerfile只需要小小的配置,就可以代替以往大量的更新工作。
3.docker的架构
工作流程:服务器A运行docker engine 服务,在docker engine 上启动很多容器container,从外网Docker Hub把image操作系统镜像pull下来,放到container容器运行。最后通过docker client对docker容器虚拟化平台进行控制。
Image 和 Container 的关系:image 可以理解为一个系统镜像,Container 是 Image 在运行时的 一个状态。
dockerhub:dockerhub 是 docker 官方的镜像存储站点,其中提供了很多常用的镜像供用户下载, 如 ubuntu, centos 等系统镜像。(这里还有私有镜像库harbor,小编在之前的博文中也介绍过:https://blog.51cto.com/14048416/2371720)
Docker的核心技术:
- Namespace — 实现 Container 的进程、网络、消息、文件系统和主机名的隔离
- Cgroup — 实现对资源的配额和度量 Docker的常用应用场景: - web应用的自动化打包和发布; - 自动化测试和持续集成、发布; - 在服务型环境中部署和调整数据库或其他的后台应用; - 从头编译或者扩展现有的OpenShift或Cloud Foundry平台来搭建自己的PaaS环境。
4.docker容器的相关技术介绍
Docker依赖于Linux内核的特性:namespace和cgroups(控制组)。 Namespace实现资源隔离,其中docker有五种命名空间: - PID:进程隔离 - NET:管理网络接口 - IPC:管理夸进程通信的访问 - MNT:管理挂载点 - UTS:隔离内核已经版本标识 Cgroups实现这个五种命名空间的管理: - 资源限制:内存、网络、磁盘、CPU - 优先级设定:设定哪些进程组使用更大的资源。 - 资源计量:计算资源组使用了多少资源。 - 资源的控制:将进程组执行和挂起。 Docker容器的能力: - 文件系统的隔离:每个容器有自己的root文件系统 - 进程隔离:每个容器都运行在自己的进程环境中 - 网络隔离:容器间的虚拟网络接口和IP地址都是分开的 - 资源隔离和分组:使用cogroup将CPU和内存之类的资源独立分配给每一个Docker容器
5.docker的安装
由于docker的安装比较容易这里小编就不在给出,但是这里需要注意:docker对centos7的支持比较好,centos6可能有有些小问题(升级kernel...):
6.给docker配置国内加速器
我们在安装好Docker CE后,使用docker pull官方镜像的时候速度非常慢,所以需要使用加速器进行加速,配置好加速器后可以非常快速的pull(拉取)Docker官方的镜像。
**第一步:**注册阿里云账号:
阿里云账号注册网址:
https://account.aliyun.com/register/register.htm?spm=5176.166170.765261.21.7150217fkh2EMl&oauth_callback=https%3A%2F%2Fwww.aliyun.com%2Fproduct%2Facr%3Fspm%3D5176.54417.765261.263.db5924592lOt4j
**第二步:**进入容器镜像服务的管理控制台:
**第三步:**配置镜像加速器:
例如我现在的操作系统是ubuntu16.04,我需要在/etc/docker文件夹下新建一个名为daemon.json的文件,并将配置信息写进去
当前Docker CE的版本是18.03:
创建daemon.json,并编辑它
将你的专属加速器网址写进去,保存退出:
然后重启docker服务
好了,现在你就可以通过加速器愉快的下载Docker官方镜像了。
7.docker搭建本地私有仓库
有时候使用 Docker Hub 这样的公共仓库可能丌方便(有时候无法访问),用户可以创建一个本地仓库供私人使用,这里使用官方提供的工具 docker-registry 来配置私有库。 docker-registry 是官方提供的工具,可以用于构建私有的镜像仓库。 实战搭建
#下载registry镜像
[root@xuegod63 ~]# docker pull registry
[root@xuegod63 ~]# docker pull busybox
#启动registry容器
docker run -d -p 5000:5000 -v /docker/images_repo:/var/lib/registry --name private_registry registry
#修改配置
echo '{ "insecure-registries":["192.168.130.101:5000"] }' > /etc/docker/daemon.json
#重启docker
systemctl restart docker
#给busyboxdabianqian打标签
docker tag busybox:latest 192.168.130.101:5000/busybox:latest
#将busybox镜像推送到远端
docker push 192.168.130.101:5000/busybox
#删除本地所有的busybox镜像
docker rmi 192.168.130.101:5000/busybox
docker rmi busybox
#从私有仓库中下载busybox镜像
docker pull 192.168.130.101:5000/busybox
如果搭建成功,以上操作都会执行成功。 观察私有库的结构:
[root@zy system]# tree /opt/registry/docker/registry/v2/
**补充:**这里介绍一下,如果是想配置私有库,并且也想配置外部的公共仓库:
编辑/etc/docker/daemon.json:
{
"registry-mirrors": [
"https://2lqq34jg.mirror.aliyuncs.com",
"https://pee6w651.mirror.aliyuncs.com",
"https://registry.docker-cn.com",
"http://hub-mirror.c.163.com"
],
"dns": ["8.8.8.8","8.8.4.4"],
"insecure-registries":["192.168.172.128:5000"]
}
根据以上的模板进行修改,小编尝试过编辑/etc/deaful/docker: DOCKER_OPTS="--insecure-registries 192.168.130.130:5000" 但是好像不起作用!
二、docker的基本操作
1.对镜像的操作
#镜像操作 在docker Hub 官方仓库中搜索镜像
[root@test ~]# docker search image_name(mysql)
注意:
获取镜像
[root@test ~]# docker pull busybox
获取特定版本的镜像
[root@test ~]# docker pull ubuntu:14.04
查看本地镜像信息
[root@test ~]# docker images
给已有镜像打标签
[root@test ~]# docker tag busybox busybox:latests
删除镜像
[root@test ~]# docker rmi image/tag
注意:如果有镜像是通过此镜像打标签的,则只是删除了这个标签而已,不影响镜像本身。当然,如果本地这个镜像只有一个标签的话,执行删除操作,将会删除此镜像文件。 如果这里有镜像已经在运行容器,强制删除
[root@test ~]# docker rim -f image_name
创建镜像之基于已有的镜像容器创建(接下来是一组操作)
[root@test ~]# docker run -ti test /bin/sh #运行并进入容器
sh-4.2$ touch test.txt #在容器中进行修改操
sh-4.2$ exit #退出容器
[root@test ~]# docker ps -a #查看所有容器
记住此容器的ID
[root@test ~]# docker commit -m "add a new file " -a "zy" 容器ID 镜像名 #提交镜像
创建镜像之导入本地模板
[root@test ~]# cat ubuntu-14.04-x86_64-minimal.tar.gz |docker import - ubuntu:14.04
存出和载入镜像
[root@test ~]# docker save -o test.tar image_name #将镜像存出到本地
[root@test ~]# docker load --input test.tar #将存出的镜像导入docker仓库
上传镜像(将镜像上传到远端仓库)
[root@test ~]# docker push image_name #注意这里需要实现登录镜像仓库,如果有自己的私有仓库,可以使用
[root@test ~]#docker push ip:port/仓库路径/image:tag
2.对容器的基本操作
创建容器
[root@test ~]# docker create -it 镜像名
查看容器
[root@test ~]#docker ps -a
新建并启动容器
[root@test ~]# docker run 镜像名 /bin/echo ‘hello world’
上一句命令会执行的操作:
检查本地是否存在指定的镜像,不存在就从共享仓库下载
利用镜像创建并启动一个容器
分配一个文件系统,并在只读的镜像层外挂载一层可读可写层
从宿主机配置的网桥接口中桥接一个虚拟接口到容器
从地址池配置一个IP给容器
执行用户指定的程序
执行完毕后容器被终止
启动一个容器并执行终端
[root@test ~]# docker run -it centos /bin/bash
-t 选项是让docker分配一个伪终端并绑定到容器,-i 则是让容器的标准输入保持打开。
守护态运行
[root@test ~]# docker run -d -h hostname centos /bin/bash -c "exec command"
查看容器日志
[root@test ~]# docker log 容器ID #获取容器的输出信息
终止容器
[root@test ~]# docker stop -t 100 容器ID # -t 是多久后终止容器
启动容器
[root@test ~]# docker start 容器ID
启动并进入一个容器
[root@test data]# docker start -it 容器ID
进入容器
[root@test ~]# docker run -t -i -h hostname 镜像名 /bin/bash #方法一(创建并进入容器)
[root@test ~]#docker attach 容器名 #方法二 (attach,进入已启动的容器)
[root@test ~]# docker exec -ti 容器ID/容器名 /bin/bash #方法三 (exec进入已启动的容器)
删除容器
[root@test ~]# docker rm [option] container
[root@test ~]#docker rm 容器ID #删除一个终止的容器
[root@test ~]#docker rm -f 容器ID #删除一个正在运行的容器
注意:
导出容器
[root@test ~]# docker export 容器ID > centos_for_run.tar
导入容器
[root@test ~]# cat centos_for_run.tar |docker import - centos:v1.0
docker容器的生命周期:
3.对仓库的基本操作
从官方仓库中查找镜像
[root@test ~]# docker search centos
从官方仓库中下载镜像当本地仓库
[root@test ~]# docker pull centos
创建和使用私有仓库
安装docker后,可以通过官方提供的registry镜像来简单搭建一套本地私有仓库环境
[root@test ~]# docker pull registry
[root@test ~]#docker run -d -p 5000:5000 registry
注意:上述命令,会后台启动一个registry容器,创建本地的私有仓库服务。
默认情况下,仓库将会放入/tmp/registry目录下,这样容器容易被删除。所以通过-v参数,指定镜像存放的目录。
[root@test ~]#docker run -d -p 5000:5000 -v /docker/images_repo registry #此时在本地将启动一个私有仓库服务,监听端口为5000
[root@test ~]#curl 127.0.0.1:5000/v1/search #访问私有仓库
小编这里只是简单的将registry私有仓库搭建完成,并没有测试,如果大家有疑问可以查看这个大神写的博客。当然如果觉得registry简单的私人仓库满足不了需求,可以使用harbor企业级的私人仓库,这里小编也有介绍:https://blog.51cto.com/14048416/2371720
当然最后介绍一下搭建私人仓库的好处: - 节约带宽 - 可以自己定制系统 - 对于微服务的发布和使用,也就是对运维部署,提供了便捷。
三、docker的进阶操作
1.数据管理
用户在使用docker的过程中,往往需要能查看容器内应用产生的数据,或者需要把容器内的数据进行备份,甚至多个容器之间进行数据的共享,这必然涉及容器的数据管理操作:数据卷、数据卷容器。
(1)数据卷
数据卷的使用,类似于Linux下对目录或者文件进行mount操作。数据卷是一个可供容器使用的特殊目录,他绕过文件系统,可以提供很多的有用特性: - 数据卷可以在容器之间共享数据和重用 - 对数据卷的修改会立刻生效 - 对数据卷的更新,不会影响镜像 - 数据卷会一直存在,直到没有容器为止 对数据卷的操作
[root@test ~]#docker run -d --name web -v /data centos #在容器中创建一个数据卷
[root@test ~]# docker run -d --name web1 -v /docker/data:/webapp centos #挂载一个主机目录作为数据卷
注意:
- 本地目录的路径必须是绝对路径,如果目录不存在docker会自动创建。
- ‘-v’后面的参数为:宿主机文件/目录:容器里对应的文件/目录
[root@test ~]# docker run -d --name web1 -v /docker/data:/webapp:or centos
上面的/docker/data:/webapp:'or' 默认情况下是rw,加了ro之后容器内挂载的数据卷的数据就无法修改了。
(2)数据卷容器
如果用户需要在容器之间共享一些持续更新的数据,最简单的方式是使用数据卷容器。数据卷容器其实就是一个普通的容器,专门用他提供数据卷供其他容器挂载使用。 容器卷容器的操作(实现多个容器之间的数据共享)
#首先,创建一个数据卷容器dbdata ,并在其中创建一个数据卷挂载到/dbdata:
[root@test data]# docker run -it -v /dbdata --name dbdata centos
#此时在这个容器中就会出现一个/dbdata目录。
#在其他容器中使用--volumes-from 来挂载dbdata容器中的数据卷:
[root@test data]# docker run -it --volumes-from dbdata --name db1 centos
[root@test data]# docker run -it --volumes-from dbdata --name db2 centos
#此时容器db1和db2都挂载同一个数据卷到相同的/dbdata目录下,三个容器任何一个该目录下的写入,其他的容器都可以看到。
'注意':
- 使用--volumes-from参数,所挂载数据卷的容器自身'不需要保持运行状态'
- 如果删除了挂载的容器(包括dbdata、db1、db2、)数据卷不会自动删除,如果想删除数据卷,必须在删除最后一个挂载他的容器时,-v指定同时删除关联的容器
(3)数据卷容器数据迁移与恢复
可以用数据卷容器对其中的数据卷进行备份,恢复,以实现数据的迁移。 数据备份
[root@test data]# docker run --volumes-from dbdata -v $(pwd):/backup --name worker centos tar cvf /backup/backup.tar /dbdata
解释:首先利用centos镜像创建一个容器worker,使用--volumes-from dbdata 参数来让worker容器挂载dbdata容器中的数据卷;
使用-v $(pwd):/backup 参数来挂载本地的当前目录到worker容器中的/backup目录;
最后worker启动后,使用tar cvf /backup/backup.tar /dbdata将其内容备份到/backup下,既宿主机的当前目录下。
数据恢复
#先创建一个带有数据卷的容器dbdata2
[root@test data]# docker run -v /dbdata --name dbdata2 centos
#然后创建另一个新的容器,挂载dbdata2的容器,并使用tar命令解压备份文件到所挂载的容器目录中:
[root@test data]# docker run --volumes-from dbdata2 -v $(pwd):/backup centos tar xvf /backup/backup.tar -C /dbdata
2.docker容器的网络配置
大量的互联网应用服务包括多个服务组件,这往往需要多个容器之间通过网络通信。Docker目前提供了映射容器端口到宿主机和容器互联机制来将容器内引用服务提供外部网络,以及通过容器互联系统让多个容器之间进行快捷的网络通信。
(1)端口映射访问容器
在启动容器的时候,如果不指定对应的参数,在容器外部是无法通过网络来访问容器内的服务的。当容器中运行一些服务时,要让外部访问这些应用时,通过-p或者-P 参数指定端口映射,-P参数docker会随机映射一个49000~49900的端口至容器内部开发的网络端口。 以registry 服务为例: #为服务指定端口 [root@test data]# docker run -d -P registry #指定具体的端口映射 [root@test data]# docker run -d -p 5000:5000 registry #其中的两个5000,表示:hostPort:containerPort [root@test data]# docker run -d -p 127.0.0.1:5000:5000 registry #映射到指定地址的指定端口 [root@test data]# docker run -d -p 127.0.0.1:5000:5000/(tcp|udp) registry #指定具体的协议
#查看端口映射
[root@test data]# docker ps
[root@test data]# docker logs -f 容器名称
[root@test data]#docker port 容器名
(2)容器互联
容器将的相互通信,它会在源和接受容器之间创建一个隧道,接受容器可以看到源容器指定的信息。在连接系统时依据容器的名称来执行,所以在创建容器的时候,使用--name 指定好容器的名称。
实现容器互联
#先创建一个新的数据库容器:
[root@test data]# docker run -d --name db training/postgres
#然后创建一个web容器,并将它连接到db容器:
[root@test data]# docker run -d -P --name web --link db:db trainng/webapp
注意:'--link db:db' :表示'连接容器的名字:此连接的别名'
[root@test data]# docker ps
这样docker就在两个容器之间创建了一个安全隧道,而且不用映射他们的端口到宿主机上。
(3)docker互联的公开信息的方式介绍
环境变量
[root@test data]# docker run --rm --name web 2 -link db:db training/webapp env
其中以DB_开头的环境变量hi提供web容器连接掉db容器使用。
更新/etc/hosts
[root@test data]# docker run -t -i --rm --link db:db training/webapp /bin/bash
其中有两个hosts信息,第一个是web,它用自己的容器ID作为主机名
第二个就是db容器的IP和主机名。
3.dockerfile的使用
(1)dockerfile的介绍
DockerFile是由一行行命令语句组成,并支持#开头的注释行。一般而言,DockerFile分为四个部分:基础镜像信息,维护者信息,镜像操作指令,和容器执行指令。
#一个简单的dockerfile
#This is DockerFile users the centos image
#Version 2 -EDITION 1
#Author zy
#Command format: Instruction [argunents/command]..
#第一行必须指定基础的镜像信息
FROM centos
#维护者信息
MAINTANER docker_user zy@email.com
#镜像的操作指令
RUN echo "deb http://archive.centos.com/centos raring main universe ">> /etc /apt/sources.list
RUN install -y nginx
RUN echo "\n daemon off;">>/etc/nginx/nginx.conf
#容器启动的执行指令
CMD /usr/sbin/nginx
(2)dockerfile文件命令详情
#注意:RUN 命令是在image构建时运行的,而CMD是在容器运行时运行的命令
#如果在运行容器是指定了运行的命令 CMD命令则会被覆盖
FROM ubuntu:14.04
MAINTAINER zy 'm18726234267@163.com'
RUN echo "Hell World!"
RUN apt-get update
RUN apt-get install -y nginx
#ENTRYPOINT指令 和CMD的不同就是,如果docker run 不指定 --entrypoint 及时后面有命令,也不会覆盖
ENTRYPOINT [ "/usr/sbin/nginx" ]
#ADD src dest 将文件和目录复制到docker镜像中 ,ADD提供了解压缩功能,可以直接解压 .tar 的压缩包
#COPY src dest 单纯的复制文件使用 COPY
#VOLUME 为容器添加卷
#WORKDIR 在创建容器时为容器添加工作目录
#ENV key=value 用于设置环境变量
#USER 容器基于什么用户身份运行(默认是root用户)
USER nginx
#USER uid
#USER user:group
#USER uid:gid
#USER user:gid
#EXPOSE 容器的暴露的端口
EXPOSE 80
#ONBUILD 容器触发器,当一个镜像被其他的镜像作为基础镜像创建时执行,会在构建过程中插入指令
#ONBUILD 的命令,不会再基础镜像中运行,哪一个以他作为基础镜像,就在哪一个镜像被构建时执行
当编译好dockerfile时,我们使用dockerfile去构建镜像
[root@test data]# docker build -t build_repo/first_image /tmp/docker_builder
注意:-t是指定镜像的标签,后面是DockerFile所在的路径
(3)dockerfile文件命令详情
具体步骤: - 从基础镜像运行一个容器 - 执行一条指令(RUN),对容器做出修改 - 执行类似docker commit的操作,提交一个新的镜像层 - 在基于刚刚提交的镜像运行一个新容器 - 在执行dockerfile的下一条指令 - 重复以上的步骤,直至所有指令执行完毕 - 在最后的结尾处,返回最后一个镜像的ID 注意:在使用dockerfile构建镜像时,只会删除中间的构建时运行的容器,不会删除中间层镜像,我们可以通过中间层镜像的ID,查看每一个步骤具体构建的内容。这里每一个步骤都使用一个中间镜像的好处时,此时会给这个中间镜像添加缓存,我们在下次重复构建时,速度非常快。当然我们也可以不使用之间缓存:docker build --no-cache。或者在dockerfile中设置环境变量: ENV REFRESH_DATE 2019-4-13,设置缓存的刷新时间。 #查看构建过程: docker history image。
4.docker资源配额控制
Docker 通过 cgroup 来控制容器使用的资源配额,包括 CPU、内存、磁盘三大方面,基本覆盖了常 见的资源配额和使用量控制。 cgroup 是 Control Groups 的缩写,是 Linux 内核提供的一种可以限制、记录、隔离过程组所使用 的物理资源(如 cpu、memory、磁盘 IO 等等) 的机制,被 LXC、docker 等很多项目用于实现过程资源 控制。cgroup 将任意过程过行分组化管理的 Linux 内核功能。cgroup 本身是提供将过程过行分组化管 理的功能和接口的基础结构,I/O 或内存的分配控制等具体的资源管理功能是通过这个功能来实现的。
(1)关于CPU使用份额
[root@test data]# docker run --help |grep cpu-shares
-c, --cpu-shares int CPU shares (relative weight) 在创建容器时指定容器所使用的 CPU 份额 值。cpu-shares 的值不能保证可以获得 1 个 vcpu 或者多少 GHz 的 CPU 资源,仅仅只是一个弹性的加权值。
默认情况下,每个docker容器的CPU份额都是1024.单独一个容器的份额是没有意义的,只有在同时运行多个容器时,容器的 cpu 加权的效果才能体现出来。
举例:
两个容器 A、B 的 cpu 份额分别为 1000 和 500。
情况一:A 和 B 正常运行,在 cpu 过行时间片分配的时候,容器 A 比容器 B 多一倍的机会获得 CPU 的时间片。
**情况二:**分配的结果取决于当时主机和其他容器的运行状态,实际上也无法保证容器 A一定能获得 CPU 时间片。比如容器 A 的过程一直是空闲的,那么容器 B 是可以获得比容器 A 更多的 CPU 时间片的。
**总结:**cgroups 只在容器分配的资源紧缺时,也就是说在需要对容器使用的资源过行限制时,才会生效。因此,无法单纯根据某个容器的 cpu 份额来确定有多少 cpu 资源分配给它,资源分配结果取决于同时运行的其他容器的 cpu 分配和容器中过程运行情况。
#分配命令
[root@test data]# docker run -it --cpu-shares 512 centos /bin/bash
CPU的周期控制 docker 提供了--cpu-period(周期)、--cpu-quota 两个参数控制容器可以分配到的 CPU 时钟周期。 --cpu-period:是用来指定容器对 CPU 的使用要在多长时间内做一次重新分配。(指定周期) --cpu-quota:是用来指定在这个周期内,最多可以有多少时间片断用来跑这个容器。 (指定在这个周期中使用多少时间片) 注意:--cpu-period:默认是0.1s,最大是1s。--cpu-quota:默认是-1,不做控制。 #命令容器过程需要每 1 秒使用单个 CPU 的 0.2 秒时间 [root@test data]#docker run -it --cpu-period 1000000 --cpu-quota 200000 centos /bin/bash
(2)docker容器资源配额控制之内存
Docker 提供参数-m, --memory=""限制容器的内存使用量。
[root@xuegod63 ~]# docker run -it -m 128m centos
(3)docker 容器资源配额控制之 IO
#容器对硬盘的最高写入速度设定为 1MB/s
[root@test data]#docker run -it -v /var/www/html/:/var/www/html --device /dev/sda:/dev/sda --device-write-bps /dev/sda:1mb centos /bin/bash