title: Docker
categories: Docker
tags: [linux,docker,运维,容器]
Docker简介
简单介绍
- 官网 www.docker.com`
- github https://github.com/docker.github.io
- 开源的容器引擎,可以让开发者打包应用以及依赖的库,然后发布到任何流行的linux发行版上,一直方便
- 由go语言编写,基于apache2.0协议发布
- 基于linux kernel,要想在wind下运行需要借助一个vm(虚拟机)来实现
- 自2013年开始,近些年发展迅猛
- docker从1.13x开始,版本分为社区版ce和企业版ee,并且基于年月的时间线形式,当前最新稳定版为17.09,参考http://blog.csdn.net/chenhaifeng2016/article/details/68062414
Docker和传统的虚拟化比较(图)
- Virtual Machines
- Docker
Docker的优势
- 启动非常快,秒级实现
- 资源利用率高,一台高配置服务器可以跑上千个docker容器
- 更快的交付和部署,一次创建和配置后,可以在任意地方运行
- 内核级别的虚拟化,不需要额外的Hypervisor支持,会有更高的性能和效率
- 易迁移,平台依赖性不强
特性 | 容器 | 虚拟机 |
---|---|---|
启动 | 秒级 | 分钟级 |
硬盘使用 | MB | GB |
性能 | 接近原生 | 弱于原生 |
系统支持量 | 单机支持上千个容器 | 一般几十个 |
Docker核心概念
- 镜像,只是一个只读的模板,类似于安装系统用到的iso文件,我们通过镜像来完成各种应用的部署
- 容器,镜像类似于操作系统,容器类似于虚拟机本身。它可以被启动、开始、停止、删除等操作,每个容器都是相互隔离的
- 仓库,存放镜像的一个场所,仓库分为公开仓库和私有仓库。最大的公开仓库是Docker hub(hub.dockker.com),国内公开仓库(dockerpool.com)
安装Docker
Docker安装
- 下载一个repo的yum源
curl https://download.docker.com/linux/centos/docker-ce.repo -o /etc/yum.repos.d/docker.repo
- 查看yum源中的信息
cat !$
- 查看一下可以安装的docker的信息
yum list | grep docker
- 安装社区版ce,下载比较慢,可以下载rpm包,yum install *.rpm
yum install -y docker-ce
- ,如果yum下载安装的时候慢,可以先下载好rpm包: https://download.docker.com/linux/centos/7/x86_64/stable/Packages/,后使用yum安装下载的rpm包
yum install -y docker-*.rpm
- 启动docker
systemctl start docker
- 查看docker进程
ps aux | grep docker
- 查看iptables规则,但是这些规则无法自动的保存
iptables -nvL
iptables -t nat -nvL
- 查看规则信息,同时save保存规则,一般没必要保存
cat /etc/sysconfig/iptables
service iptables save
- 清空iptables规则
iptables -t nat -F
- 查看规则
iptables -t nat -nvL
- 重启docker,规则就回来了
systemctl restart docker
- 如果删除了docker 的iptables,docker的网路会出现问题,需要重启docker和容器
镜像的管理
-
镜像的下载
docker pull centos
-
配置docker加速器,参考:http://blog.csdn.net/xlemonok/article/details/71403534
-
vim /etc/docker/daemon.json
-
加入类容
-
{ "registry-mirrors":["https://dhq9bx4f.mirror.aliyuncs.com"] }
-
说明:这个url为加速器地址,需要自行到阿里云申请,配置完加速器之后,再次重新docker pull centos会快的多
-
-
-
查看本地的镜像
docker images
-
搜索镜像
docker search jumpserver
-
配置完成加速器之后需要重启docker
systemctl restart docker
-
给centos镜像打一个tag标签名字
docker tag centos aminglinux_centos
-
给centos打一个tag标签名字,同时TAG也改名字
docker tag centos test111:171104
-
把镜像启动为容器,-i表示让容器的标准输入打开,-t表示分配一个伪终端,-d表示后台启动,要把-i -t -d放到镜像的名字前边
docker run -itd centos
-
查看启动的容器和查看所有的容器
docker ps
docker ps -a
-
删除镜像,后边的参数可以是tag,如果是tag,实际上删除的是tag。当后边的参数是镜像的ID的时候,会彻底的删除整个镜像,所有标签也会一同删除
docker rmi test111:171104
- 如果没有指定tag:171104,默认是latest
docker rmi Images_ID
通过容器创建镜像
Docker通过容器创建镜像
- 查看运行的容器
docker ps
- 进入已经启动的容器中,后边跟上容器ID,加上bash是为了开启一个bash进程
docker exec -it container_ID bash
- 进入容器之后查看空间大小
df -h
- 查看内存
free
- 安装一个nettool工具,支持ifconfig、ip add等命令
yum install -y net-tools
- 退出容器使用快捷ctrl+d或者使用
exit
- 将容器做成镜像,-m添加说明,-a指定作者,new_image_name为保存之后的镜像的名字
docker commit -m "install net-tools " -a "author" container_ID new_image_name
- 查看新的镜像
docker images
- 用nwe_image_name创建一个新的容器,测试刚才安装过的net-tools在新的镜像中有了没有
docker run -itd new_image_name bash
docker exec -itd container_ID
或者docker exec -it container_Name
ifconfig
ping www.baidu.com
- 可以在宿主机上查看容器的网卡
ifconfig
通过模板创建镜像
Docker使用模板创建镜像
- 首先下载一个系统模板:http://openvz.org/Download/templates/precreated
- 虚拟机系统中下载
wget http://openvz.org/Download/templates/precreated /centos-*.tar.gz
- 将windows系统中的模板上传到linux系统中
rz
- 导入模板,centos6是给镜像取得名字
cat centos-*.tar.gz | docker import - centos6
- 查看模板的大小
du -sh centos-*.tar.gz
- 查看镜像
docker images
- 使用导入的镜像启动一个容器
docker run -itd centos6 bash
- 进入到启动的容器当中
docker exec -it container_ID bash
- 在容器中查看系统版本
cat /etc/issue
- 在容器中测试是否有一些命令
ifconfig
- 在容器中查看系统内核,内核使用的和宿主机使用的是一样的内核
uanme -a
- 退出容器
exit
- 查看宿主机的内核
uname -a
- 将镜像导出成一个文件
docker save -o wenjian_name.tar image_name
- 将文件导入恢复成镜像
docker load --input wenjian_name.tar
或者docker load < wenjian_name.tar
- 查看文件的大小
du -sh wenjian_name.tar
- 删除镜像
docker rmi image_ID
- 删除容器
docker rm -f container_ID
- 停止容器
docker stop container_ID
- 可以将自己的镜像上传到dockerhub官方网站上去,但是需要先注册一个用户
docker push image_name
容器管理
Docker容器管理
- 创建一个容器,但是这个容器没有启动,docker run的用法一样,但是docker run是运行的容器
docker create it image_name bash
- 查看容器
docker ps -a
- 启动创建好的容器,也可以使用restart和stop重启或者停止容器
docker start container_ID
- 查看启动之后的容器
docker ps
- 之前使用的docker run表示先create再start,没有使用-d选项,只是启动,使用exit退出之后就停止运行了
docker run -it image_name bash
exit
docker ps
- 创建一个容器直接运行在后台,不需要显示终端bash,同时执行命令
docker run -d image_name bash -c "while:;do echo "123";sleep 2;done"
- 给容器自定义名字,不加–name会自动生成一个名字
docker run itd --name container_name image_name bash
- 通过名字进入到启动的容器当中
docker exec -it container_name bash
- 让容器运行一段命令之后就退出,直接删除,睡30秒之后自动退出删除容器
docker run --rm -it image_name bash -c "sleep 30"
- 获取容器运行的历史信息,先运行一个容器执行一个输出命令
docker run -itd image_name bash -c "echo 123"
docker logs container_ID
- 进入一个后台运行的容器使用docker attach,但是想要退出终端exit之后,容器也就退出了
docker attach container_ID
- 使用docker exec进入容器,临时打开一个终端,但是退出之后容器依然运行着
docker exec -it container_ID bash
- 删除容器,如果是删除运行者的容器,强制删除加上-f
docker rm -f container_ID
- 导出容器,可以迁移到其他的机器上去,但是要导入
docker export container_ID > file.tar
- 导入文件生成镜像
cat file.tar | docker import - image_name
仓库管理
Docker仓库管理
-
下载镜像registry,registry是docker官方提供的一个镜像,可以通过它创建本地的docker私有仓库
docker pull registry
-
重启docker
systemctl restart docker.service
-
启动容器
docker start container_ID
-
以registry镜像启动容器,-p会把容器的端口映射到宿主机上,左边是宿主机的端口,右边是容器的端口,
docker run -d -p 5000:5000 registry
-
查看启动的容器
docker ps
-
测试访问5000端口
talnet 127.0.0.1 5000
-
访问这个仓库
curl 127.0.0.1:5000/v2/_catalog
-
将一个容器上传到私有仓库
-
标记一下tag,必须带有私有仓库的ip:port
docker tag image_name 172.3.2.11:5000/centos
-
把标记的镜像推送到私有仓库,但是可能此时会失败,因为默认使用的是https,但是就是要用http
docker push 172.3.2.11:5000/centos
-
更改配置文件
vi /etc/docker/daemon.json
,指定ip和端口-
{ "insecure-registries":["172.3.2.11:5000"] }
-
-
重启doker和registry创建的容器
systemctl restart docker
docker start container_ID
-
重新push
docker push 172.3.2.11:5000/centos
-
-
上传镜像到仓库成功之后,使用curl查看仓库中的镜像
curl 127.0.0.1:5000/v2/_catalog
-
从私有仓库中将镜像pull下来
-
先配置dameon.json指向私有仓库ip:port,这个配置不影响到公有仓库去下载docker镜像
-
{ "insecure-registries":["172.3.2.11:5000"] }
-
-
docker pull 172.3.2.11:5000/centos
-
数据管理
Docker数据管理
- 挂载本地的目录到容器里,-v指定挂载的目录,左边是宿主机的/data/本地目录,右边/data是容器的目录,会在容器中自动创建
docker run itd -v /data/:/data image_name bash
- 进入容器同时查看/data目录下的信息
docker exec -it container_ID bash
ls -l /data/
- 在容器的/data/目录中创建123
mkdir /data/123
- 退出容器,查看宿主机本地/data/目录
exit
ls -l /data/
- 挂载数据卷,当一个容器已经存在了,而且目录映射也完成了,这个时候启动另外一个容器,同时挂载之前一个容器的数据卷,这样后者完成和前者一样的目录映射,前者叫做数据卷容器
docker run -itd --volumes-from old_container_name image_name bash
- 进入到新的容器中同时查看目录的映射情况
docker exec -it container_ID bash
ls -l /data/
- 定义数据卷容器,有的时候我们需要多个容器之间共享数据,类似于linux中的NFS,所以搭建一个专门的数据卷容器,然后其他容器直接挂载该数据卷就行了
- 建立数据卷容器,这里的/data/是容器的/data目录,并非本地的/data/目录,vol_name是数据卷
docker run -itd -v /data --name vol_name image_name bash
- 挂载该数据卷
docker run -itd --volumes-from vol_name image_name bash
- 建立数据卷容器,这里的/data/是容器的/data目录,并非本地的/data/目录,vol_name是数据卷
- 建立一个home软链接
ln -s /data/ /home/
数据卷备份恢复
Docker数据卷的备份和恢复(主要是解决容器和宿主机之间没有做映射的数据处理)
- 数据卷备份
- 创建一个本机的目录
mkdir /data/backup
- 新建容器,同时挂载数据卷,同时做一个目录映射,将本地的/data/backup挂载到容器的/backup目录下,然后将/data/目录下的文件打包成data.tar文件放到/backup目录下面
docker run --volumes-from vol_name -v /data/backup:/backup image_name tar cvf /backup/data.tar /data
- 创建一个本机的目录
- 恢复
- 思路:新建一个数据卷容器,再建一个新的容器并挂载该数据卷容器,然后将tar包解包
- 新建数据卷容器
docker run -itd -v /data/ --name vol_name2 image_name bash
- 挂载数据卷新建容器,并解包
docker run --volumes-from vol_name2 -v /data/backup/:/backup image_name tar xf /backup/data.tar
Docker网络模式
Docker网络模式
- host模式,使用docker run时使用–net=host指定,网络和宿主机一样,网卡什么的都是一样的,容器中使用的ip就是宿主机的ip
- container模式,使用–net=container:container_ID/container_name,多个容器使用的共享网络,使用的ip是一样的
- none模式,使用–net=none指定,这种模式下不会有任何网络,无网卡
- bridge模式,使用–net=bridge指定默认模式,如果不指定就是这种网络模式,这种网络模式会给每一个容器分配一个独立的Network Namespace。类似于vmware的net网络模式。同一个宿主机上的所有容器会在同一网段下,相互之间可以通信,局域网一样,对外是访问不到的
Docker网络管理-外部访问容器
- 先创建运行或者进入一个容器
docker exec -it container_ID bash
- 在该容器中安装httpd(web)服务,并启动,如安装一个nginx
- 安装epel-release
yum install -y epel-release
- 安装nginx
yum install -y nginx
- 启动nginx,遇到一个权限问题(operation not permitted)
systemctl start nginx
- 退出容器
exit
- 安装epel-release
- 将安装nginx的容器导出为一个镜像
docker commit -m "install nginx" -a "author" container_ID new_image_name
- 查看新的镜像
docker images
- 使用新的镜像创建启动一个容器,指定端口映射
docker run -itd -p 8088:80 new_image_name bash
operation not permitted
Operation not permitted
- 新建的容器在启动nginx或者httpd服务的时候会报错(Failed to get D-Bus connection:Operation not permitted)
- 原因是dbus-daemon没有启动,以下解决该问题
- 启动容器时,加上–privilieged -e “container=docker”,并且最后的命令改为/usr/sbin/init
docker run -itd --privileged -e "container=docker" (-p 8088:80) new_image_name /usr/sbin/init
- 启动容器时,加上–privilieged -e “container=docker”,并且最后的命令改为/usr/sbin/init
- 进入容器
docker exec -it container_ID bash
- 启动nginx服务
systemctl start nginx
- 在容器中查看nginx进程
ps aux | grep nginx
- 在容器中测试访问,默认端口是80
curl localhost
- 退出容器,在宿主机上进行访问容器,8088端口
curl localhost:8088
- 其他的机器访问容器
curl ip:8088
配置桥接网络
Docker网络管理-配置桥接网络
-
为了使本地网络中的机器和Docker容器更方便的通信,经常会遇到将Docker容器配置到和主机同一网段的需求,这就需要将Doker容器和主机de网卡桥接起来,再给容器配置上ip就可以了
-
进入到网卡目录,查看网卡信息
cd /etc/sysconfig/network-scripts/
-
要做桥接,就先将宿主机的网卡ens33进行复制
cp ifcfg ens33 ifcfg-br0
-
编辑新网卡的信息
-
vi ifcfg-br0
-
TYPE=Bridge NAME=br0 DEVICE=br0 #UUID=...
-
-
-
编辑宿主机的网卡信息
-
vi ifcfg-ens33
-
#UUID=... #DNS1=... #DNS2=... #IPADDR=... #PREFIX=... #GATEWAY=... BRIDGE=br0
-
-
-
重启一下网络
systemctl restart network
-
安装pipework
git clone https://github.com/jpetazzo/pipework
-
复制可执行文件pipework
- cp pipework/pipework /usr/local/bin/
-
开启一容器
docker run -itd --net=none --name container_name image_name bash
-
进入容器,之后退出容器
docker exec -it container_ID bash
exit
-
使用pipework配置ip_address,ip_address是本网段中设置的一个ip地址,gateway是网管
pipework br0 container_name(或container_ID) ip_address/24@gateway
-
重新进入配置了ip地址的容器,查看ip
ifconfig
-
使用别的机器访问
ping ip_address
-
一般的nat和pipework的桥接不一样,pipework实现了真正的桥接方式
针对宿主机的ens37网卡做桥接
- 使用docker的桥接实现多个网卡的连接,一个网卡连接外网,一个网卡连接内网(如何实现外网和内网的设置和连接)
Dockerfile(上)
Dockerfile创建镜像-Dockerfile格式
- FROM //指定基于哪个基础镜像
- 格式:FROM 或者FROM :
- 示例
FROM centos
FROM centos:latest
- MAINTAINER //指定作者信息
- 格式:MAINTAINER
- 示例
MAINTAINER author author@linux.com
- RUN //运行镜像
- 格式:RUN 或者RUN [“executable”,“param1”,“param2”]
- 示例
RUN yun install httpd
RUN ["/bin/bash","-c","echo hello"]
- CMD //运行命令
- 三种格式
CMD ["executable","param1","param2"]
CMD command param1 param2
CMD ["param1","param2"]
- 和RUN相似,但是CMD用来指定容器启动时用到的命令,只能有一条命令,如启动nginx
CMD ["/bin/bash","/usr/local/nginx/sbin/nginx","-c","/usr/local/nginx/conf/nginx.conf"]
- 三种格式
- EXPOSE //这个用来指定要映射出去的端口
- 格式:EXPOSE […]
- 示例
EXPOSE 22 80 8443
- 这个用来指定映射出去的端口,比如容器内部我们启动了sshd和nginx,所以我们需要把22和80端口暴露出去,这个需要配合-P来工作,也就是说在启动容器的时候,需要加上-P,让它自动分配端口。如果我们想指定具体的端口,需要使用-p来指定
- ENV //用来指定环境变量
- 格式:ENV
- 示例
ENV PATH /usr/local/mysql/bin:$PATH
- ENV主要是为后续的RUN命令指定一个环境变量,我们可以定义一些自定义的变量
ENV MYSQL_version 5.6
- ADD //将本地的一个文件或者目录拷贝到容器的某个目录里
- 格式:ADD
- 示例
ADD <conf/vhosts></usr/local/nginx/conf>
- ADD //将本地的一个文件或者目录拷贝到容器的某个目录里,其中src为Dockerfile所在目录的相对路径,他也可以是一个url
- COPY
- 格式:COPY
- COPY的使用和ADD一样,但是COPY不支持url
- ENTRYPOINT //格式类似于CMD
- 容器启动时要执行的命令,它和CMD很像,也是只有一条生效,如果写多个命令的话,最后一条命令生效
- 与CMD不同的是:CMD可以被docker run指令覆盖的,而ENTRYPOINT不能覆盖。如,容器的名字为container_name,我们在Dockerfile中指定如下CMD:
CMD ["/bin/echo","test"]
- 如果启动容器的命令是
docker run container_name
,这样会输出test - 如果启动容器执行的命令是
docker run -it container_name bash
,结果是什么都不会输出
- ENTRYPOINT不会覆盖,而且会比CMD或者docker run指定的命令要靠前执行
ENTRYPOINT ["echo","test"]
dcoker run -it container_name 123
,输出的结果是test 123,相当于执行的命令是echo test 123
Dockerfile格式(下)
本节的内容继续上一章节的内容
- VOLUME
- 格式:VOLUME ["/data"]
- 创建一个可以从本地主机或其他容器挂载的挂载点,相当于docker -v后边跟的目录
- USER
- 格式:USER daemon
- 指定运行容器的用户
- WORKDIR
- 格式:WORKDIR /path/to/workdir
- 为后续的RUN、CMD或者ENTRYPOINT指定工作目录
Dockerfile示例(安装nginx上)
-
先下载nginx的配置文件
wegt http://www.apelearn.com/study_v2/.nginx_conf
-
vim Dockerfile
-
## Set the image to CentOS 基于centos镜像 FROM centos # File AUthor / Maintainer 作者信息 MAINTAINER author_name author@eamil.com # Install necessary tools 安装一些依赖的包或者需要的包 RUN yum install -y pcre-devel wget net-tools gcc zlib zlib-devel make openssl-devel # Install Nginx 下载nginx包,放到当前目录下,虽然没有指定workdir,默认是在根下边 ADD http://nginx.org/download/nginx-1.8.0.tar.gz . RUN tar zxvf nginx-1.8.0.tar.gz # 创建目录加上-p,级联创建目录 RUN mkdir -p /usr/local/nginx # 进入到nginx目录进行编译 RUN cd nginx-1.8.0 && ./configure --prefix=/usr/local/nginx && make && make install # 删除掉原来自带的nginx.conf文件 RUN rm -fv /usr/local/nginx/nginx.conf # 下载配置文件到指定的目录文件 ADD http://www.apelearn.com/study_v2/.nginx_conf /usr/local/nginx/conf/nginx.conf # Expose ports 暴露端口 EXPORSE 80 # Set the default command to execute when creating a new container 启动服务,为什么要加上tail命令呢?由于前边的命令执行完成容器就自动的停止了,加上tail这样就永远执行不完,容器就一直run着 ENTRYPOINT /usr/local/nginx/sbin/nginx && tail -f /etc/password
-
-
如何使用Dockerfile?
-
创建镜像:-t是为了指定新的镜像的名字,docker build指定的是文件是Dockerfile,默认就去build这个文件了,其中 . 表示当前路径下去找这个文件
docker build -t new_image_name .
-
执行以上的命令可能遇到错误问题,网络问题,需要重启一下docker服务
systemctl restart docker
-
检查build是否能进行,先docker exec 进入一个容器中,看能不能联网
-
重新build一下
docker build -t new_image_name
Dockerfile示例(安装nginx下)
- 查看新的镜像
docker images
- 从新的镜像中创建运行一个新的容器
docker run -itd -p 81:80 new_image_name bash
- 进入新的容器
docker exec -it container_ID bash
- 在容器中查看nginx的情况
ps aux | grep nginx
- 从宿主机访问容器的81端口
curl 127.0.0.1:81
用docker compost部署服务
用Docker compose部署服务
- docker compose可以方便我们快捷高效的管理容器的启动,停止,重启等操作,它类似 于linux下的shell脚本,基于yaml语法,在该文件里,我们可以描述应用的架构,比如用设么镜像,数据卷,网络模式,监听端口等信息。我们可以在一个compose文件中定义一个多容器的应用(比如jumpserver),然后通过该compose来启动这个应用。
- 安装compose方法如下
curl -L https://github.com/docker/compose/releases/download/1.17.0-rc1/docker-compose-'uname -s'-'uname -m' > /usr/local/bin/docker-compose
chmod 755 !$
docker-compose version 查看版本信息
- Compose区分Version 1和Version 2(Compose 1.6.0+,Docker Engine 1.10.0+)。Version 2支持更多的指令。Version 1没有申明版本默认是“version 1”。version 1 将来会被抛弃。
docker compose示例
-
编辑docker-compose.yml文件的内容
-
vim docker-compose.yml
-
内容下载:https://coding.net/u/aminglinux/p/yuanke_centos7/git/blob/master/25docker/docker-compose.yml
-
version: "2" #使用2版本 services: #接下来就是一些容器镜像的操作 app1: #容器的名字 image: centos_nginx #镜像的名字 ports: #端口的映射 - "8080:80" networks: #使用哪一个网络(下边定义) - "net1" volumes: #做一个目录的映射(如果不写:只写了/data/就表示一个数据卷,把/data做一个分享) - /data/:/data app2: image: centos_with_nettool networks: - "net2" volumes: - /data/:/data1 entrypoint: tail -f /etc/passwd networks: net1: driver: bridge #指定模式,默认是bridge net2: driver: bridge
-
-
通过docker-compose.yml的配置将容器启动起来
docker-compose up -d
-
查看启动的容器
docker-compose ps
-
停掉
docker-compose rm -f
-
查看docker的命令帮助
docker --help