一、docker简介
1.1 什么是docker
- Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从Apache2.0协议开源。
- Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。
- 容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。
简单来说:
解决了运行环境和配置问题的软件容器,方便做持续集成并有助于整体发布的容器虚拟化技术。
1.2 为什么用docker
-
1、 简化程序
Docker 让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,便可 以实现虚拟化。Docker改变了虚拟化的方式,使开发者可以直接将自己的成果放入Docker中进行管理。方便快捷已经 是 Docker的最大优势,过去需要用数天乃至数周的 任务,在Docker容器的处理下,只需要数秒就能完成。 -
2、 避免选择恐惧症
如果你有选择恐惧症,还是资深患者。Docker 帮你 打包你的纠结!比如 Docker 镜像; Docker 镜像中包含了运行环境和配置,所以 Docker 可以简化部署多种应用实例工作。比如 Web 应用、后台应用、数 据库应用、大数据应用比如 Hadoop 集群、消息队列等等都可以打包成一个镜像部署。 -
3、 节省开支
一方面,云计算时代到来,使开发者不必为了追求效果而配置高额的硬件,Docker 改变了高性能必然 高价格的思维定势。Docker 与云的结合,让云空间得到更充分的利用。不仅解决了硬件管理的问题,也改变了虚拟 化的方式。
-
4、 持续交付和部署
对开发和运维(DevOps)人员来说,最希望的就是一次创建或配置,可以在任意地方正常运行。使用 Docker 可以通 过定制应用镜像来实现持续集成、持续交付、部署。开发人员可以通过 Dockerfile 来进行镜像构建,并结合 持续集成 (Continuous Integration) 系统进行集成测试,而运维人员则可以直接在生产环境中快速部署该镜像,甚至结合 持续部署(Continuous Delivery/Deployment) 系统进行自动部署。而且使用 Dockerfile 使镜像构建透明化,不仅仅开发团队可 以理解应用运行环境,也方便运维团队理解应用运行所需条件,帮助更好的生产环境中部署该镜像 -
5、 更轻松的迁移
由于 Docker 确保了执行环境的一致性,使得应用的迁移更加容易。Docker 可以在很多平台上运行,无论是物理机、 虚拟机、公有云、私有云,甚至是笔记本,其运行结果是一致的。因此用户可以很轻易的将在一个平台上运行的应 用,迁移到另一个平台上,而不用担心运行环境的变化导致应用无法正常运行的情况
1.3 容器与虚拟机
1.3.1 区别
- 实现原理技术不同
-
虚拟机是用来进行硬件资源划分的完美解决方案,利用的是硬件虚拟化技术,如此VT-x 、 AMD-V会通 过一个 hypervisor 层来实现对资源的彻底隔离。
-
容器则是操作系统级别的虚拟化,利用的是内核 的 Cgroup 和 Namespace 特性,此功能通过软件 来实现,仅仅是进程本身就可以实现互相隔离,不需要任何辅助。
-
使用资源方面不同
- Docker 容器与主机共享操作系统内核,不同的容器之间可以共享部分系统资源,因此更加 轻量级, 消耗的资源更少。
- 虚拟机会独占分配给自己的资源,不存在资源共享,各个虚拟机之间近乎完全隔 离,更加重量级,也 会消耗更多的资源
-
应用场景不同
-
若需要资源的完全隔离并且不考虑资源的消耗,可以使用虚拟机 。
-
若是想隔离进程并且需要运行大量进程实例,应该选择 Docker 容器
二、docker平台架构
2.1 基本组成
Docker 包括三个基本概念:
-
镜像(
Image
)Docker 镜像(Image)就是一个只读的模板。镜像可以用来创建 Docker 容器,一个镜像可以创建很多容器。它也相当于是一个root文件系统。比如官方镜像 centos:7 就包含了完整的一套 centos:7 最小系统的 root 文件系统。
镜像类似于一个类,而容器则类似于实例化这个类所产生的对象。容器里的东西都是基于镜像的基础上生成而来。
-
容器(
Container
)Docker 利用容器(Container)独立运行的一个或一组应用,应用程序或服务运行在容器里面,容器就类似于一个虚拟化的运行环境,容器是用镜像创建的运行实例。
也可以把容器看做是一个简易版的 Linux 环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。
-
仓库(
Repository
)仓库(Repository)是集中存放镜像文件的场所。
类似于github仓库,存放各种git项目的地方;
Docker公司提供的官方registry被称为Docker Hub,存放各种镜像模板的地方。理解了这三个概念,就理解了 Docker 的整个生命周期。
举个简单的例子来解释镜像与容器的关系
- 镜像 === 生成 ===> 容器
大家都有安装过操作系统,不管是在虚拟机还是物理机上面,我们都需要一个系统镜像文件,比如Windows的iso镜像文件,当我们安装过程中需要镜像才能把系统安装到机器(虚拟机或物理机)上,安装成功之后我们所看见的界面(windows操作系统)就可以理解为一个容器。这就是镜像生成容器。
- 容器 === 生成 ===> 镜像
如果我们发现安装window 后,没有QQ,没有微信,没有网易云音乐等这些软件。此时你就在想,我下一次给电脑安装Windows系统时必须要有这些软件,我想只要成功安装window了就自带这些软件,所以我们在安装好需要的软件后,把window系统打包成一个镜像,此时的镜像就包含了你需要的软件了。 这就是容器生成镜像。
不知道这个例子能不能说明白两者之间的关系
2.2 docker运行原理
- 平台结构图
Docker是一个Client-Server结构的系统,Docker守护进程运行在主机上, 然后通过Socket连接从客户端访问,守护进程从客户端接受命令并管理运行在主机上的容器。 容器,是一个运行时环境,就是我们前面说到的集装箱。
- docker组件图
三、Docker 基本使用
3.1 安装&卸载
3.1.1 安装
从 2017 年 3 月开始 docker 在原来的基础上分为两个分支版本: Docker CE 和 Docker EE。 Docker CE 即社区免费版,Docker EE 即企业版,强调安全,但需付费使用。 本文介绍 Docker CE 的安装使用。
- 移除旧版本
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-selinux \
docker-engine-selinux \
docker-engine
若之前未安装则无需移除
-
添加软件信息源
源1:(官方推荐) yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo 源2:(阿里云源) sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
-
更新yum源
sudo yum makecache fast
-
安装Docker-CE
sudo yum install docker-ce -y
-
启动docker
systemctl start docker
-
重启Docker服务
systemctl restart docker
-
查看docker版本
docker --version
3.1.2 卸载
-
停止docker
systemctl stop docker
-
移除docker
yum remove docker-ce docker-ce-cli containerd.io
-
移除相关文件
rm -rf /var/lib/docker rm -rf /var/lib/containerd
3.2 Docker镜像加速器
使用Docker 的时候,需要经常从官方获取镜像,但是由于显而易见的网络原因,拉取镜像的过程非 常耗时,严重影响使用Docker 的体验。因此 DaoCloud 推出了加速器工具解决这个难题,通过智能路由和缓存机制,极大提升了国内网络访问 Docker Hub 的速度, 并得到了 Docker 官方的大力推荐。
Docker 官方和国内很多云服务商都提供了国内加速器服务
- docker官方提供的中国
register mirror
(好像不能使用了) - 阿里云加速器:https://<你的ID>.mirror.aliyuncs.com
- 七牛云加速器 :https://reg-mirror.qiniu.com
- 网易:https://hub-mirror.c.163.com/
设置加速器
在/etc/docker/daemon.json
中写入如下内容(如果文件不存在请新建该文件)
{"registry-mirrors":["https://reg-mirror.qiniu.com/"]}
# 注意,一定要保证该文件符合 json 规范,否则 Docker 将不能启动
重新启动docker服务
systemctl daemon-reload # 重载daemon.json文件
systemctl restart docker # 重新启动docker
检测加速器是否生效
ubuntu:~# docker info
....
Registry Mirrors:
https://reg-mirror.qiniu.com
3.3 docker 常用命令
3.3.1 镜像相关
-
拉取镜像
docker pull [选项] [Docker Registey 地址[:端口号]/] 仓库名[:标签]
具体的选项可以通过 docker pull --help 命令看到,这里我们说一下镜像名称的格式。 - Docker 镜像仓库地址: 地址的格式一般是 <域名/IP>[:端口号]。默认地址是 Docker Hub。 - 仓库名:这里的仓库名是两段式名称, 即 <用户名>/<软件名>。 对于 Docker Hub,如果不给出用户名,则默认为 library, 也就是官方镜像。
docker pull python:3.8 # 若不写 :3.8 则默认下载最新的镜像
-
运行镜像(生成容器)
docker run -it python:3.8 /bin/bash 参数说明: -i: 交互式操作。 -t: 终端。 -d: 后台运行镜像,不需要加-i和-t ubuntu:15.10: 这是指用 ubuntu 15.10 版本镜像为基础来启动容器。 /bin/bash:放在镜像名后的是命令,这里我们希望有个交互式 Shell,因此用的是 /bin/bash
-
搜索镜像
[root@guoweixin ~]# docker search --help Usage: docker search [OPTIONS] TERM Search the Docker Hub for images Options: -f, --filter filter Filter output based on conditions provided # 根据提供的条件过滤器输出 --format string Pretty-print search using a Go template # ⽤Go模板打印出漂亮的搜索结果 --limit int Max number of search results (default 25) # 搜索结果的最⼤数量(默认值为25) --no-trunc Don't truncate output # 不要截断输出
docker search python
-
列出镜像
列出已下载的镜像信息
root@rionserver:~# docker images REPOSITORY TAG IMAGE ID CREATED SIZE python 3.8 050b8443e26e 2 weeks ago 912MB
- REPOSITORY:表示镜像的仓库源
- TAG:镜像的标签
- IMAGE ID:镜像ID
- CREATED:镜像创建时间
- SIZE:镜像大小
镜像体积 如果仔细观察,会注意到,这里标识的所占用空间和在 Docker Hub 上看到的镜像大小不同。这是因
为 Docker Hub 中显示的体积是压缩后的体积。在镜像下载和上传过程中镜像是保持着压缩状态的,因此
Docker Hub 所显示的大小是网络传输中更关心的流量大小。而 docker image ls 显示的是镜像下载到本地后,展
开的大小,准确说,是展开后的各层所占空间的总和,因为镜像到本地后,查看空间的时候,更关心的是本地
磁盘空间占用的大小。 另外一个需要注意的问题是,docker image ls 列表中的镜像体积总和并非是所有镜像实
际硬盘消耗。由于 Docker 镜像是多层存储结构,并且可以继承、复用,因此不同镜像可能会因为使用相同的基
础镜像,从而拥有共同的层。由于 Docker 使用 Union FS,相同的层只需要保存一份即可,因此实际镜像硬盘占
用空间很可能要比这个列表镜像大小的总和要小的多。
-
删除镜像
docker rmi <ImageName> | <ImageID> # 可以是镜像ID或者是镜像名
要删除镜像必须确认此镜像⽬前没有被任何容器使⽤
-
查看镜像的ID
docker images -q
-
查看镜像的制作历程
docker history <ImageName>
-
保存镜像
备份本地仓库的镜像
-
1 ⽤ save ⼦命令将本地仓库的镜像保存当前目录下
docker save -o tomcat.guo.tar 镜像名称
-
2 将本地目录下的镜像备份文件导⼊到本地Docker 仓库
# ⽅式⼀(不输出详细信息): [root@localhost ~]# docker load -i tomcat.guo.tar # ⽅式⼆(输出详细信息): [root@localhost ~]# docker load < tomcat.guo.tar
-
3.3.2 容器相关
所有运行的容器都是依赖于镜像而生成。
-
查看容器状态
查看每个容器的详细情况(CPU的使用率,内存的使用率等)
docker stats
查看容器的整体情况
docker ps -a # -a 表示显示全部的容器,不加则表示只显示正在运行的容器
-
生成容器
docker run -it ubuntu:15.10 /bin/bash -i 保持和 docker 容器内的交互,启动容器时,运⾏的命令结束后,容器依然存活,没有退出(默认是会退出,即停⽌的) -t 为容器的标准输⼊虚拟⼀个tty -d 后台运⾏容器 --rm 容器在启动后,执⾏完成命令或程序后就销毁 --name 给容器起⼀个⾃定义名称 -p 宿主机:内部端口 参数说明: -i: 交互式操作。 -t: 终端。 -d: 后台运行镜像,不需要加-i和-t --rm: 容器在启动后,执⾏完成命令或程序后就销毁 --name: 给容器起⼀个⾃定义名称 -p: 宿主机:内部端口 -v: 宿主机目录:容器内部目录 (挂载目录) ubuntu:15.10: 这是指用 ubuntu 15.10 版本镜像为基础来启动容器。 /bin/bash:放在镜像名后的是命令,这里我们希望有个交互式 Shell,因此用的是 /bin/bash
-
开始 / 停止 / 重启运行容器
docker start/stop/restart <ContainerName> | <ContainerID> # 可以使用容器名或容器ID
-
进入后台在运行的容器
docker exec -it <ContainerName> | <ContainerID> /bin/bash
-
查看容器日志
当我们以后台的方式启动容器,控制台则不会显示启动信息,我们可以通过logs来查看
docker logs [options] <ContainerName> | <ContainerID> # options -since : 此参数指定了输出日志开始日期,即只输出指定日期之后的日志。 -f : 查看实时日志 -t : 查看日志产生的日期 -tail=10 : 查看最后的10条日志
-
容器与宿主机文件交换
docker cp [OPTIONS] CONTAINER:PATH LOCALPATH //容器中 复制到 宿主机 # 宿主机复制一个图片到容器中:将png图片复制到了容器指定目录下 # docker cp 1.png tomcat2:/usr/local/tomcat/webapps/ROOT docker cp [OPTIONS] LOCALPATH|- CONTAINER:PATH //宿主机 复制到 容器中 # 将容器内的index.jsp 复制出来到/root目录下 docker cp tomcat2:/usr/local/tomcat/webapps/ROOT/index.jsp /root # CONTAINER:可以是id也可以是名称
-
容器生成镜像
docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]] # 提交 参数 容器名称 镜像名称:版本
OPTIONS
说明:- -a :提交的镜像作者;
- -c :使用Dockerfile指令来创建镜像;
- -m :提交时的说明文字;
- -p :在commit时,将容器暂停。
runoob@runoob:~$ docker commit -a "runoob.com" -m "my apache" a404c6c174a2 mymysql:v1 sha256:37af1236adef1544e8886be23010b66577647a40bc02c0885a6600b33ee28057 runoob@runoob:~$ docker images mymysql:v1 REPOSITORY TAG IMAGE ID CREATED SIZE mymysql v1 37af1236adef 15 seconds ago 329 MB
四、案例:打包一个含有flask 的镜像
4.1 需求
只要通过镜像生成容器时,开放5000端口并启动web服务。使外界可以访问flask
项目
4.2 实现
-
下载python镜像
docker pull python:3.8
-
生成容器
docker run -it --name flask_demo python:3.8 /bin/bash
-
安装flask环境
pip install flask -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com # 也可以不要pip源,直接安装flask # pip install flask
-
写一个flask demo
我们在
/root/flask/app.py
写入一个demofrom flask import Flask app = Flask(__name__) @app.route('/') def index(): return 'this is flask index!' if __name__ == '__main__': app.run(host='0.0.0.0',port=5000)
-
将
app.py
复制到容器中去# 1.容器内创建目录 root@container:/# mkdir /root/flask # 2.宿主机下复制文件到容器中 docker cp /root/flask/app.py flask_demo:/root/flask/app.py
这里也可以使用挂载的方式把文件复制到容器中,不过复制到容器后的文件必须转移到其他目录,因为容器中所挂载的目录,在打包成镜像时是不会包含挂载目录下的文件的。
# 实现方式二 docker run -it --name flask_demo2 -v /root/flask/:/root/flask python:3.8 /bin/bash # 宿主机目录 : 容器目录
-
打包镜像
# 1.停止运行docker container root@rionserver:~# docker stop flask_demo flask_demo root@rionserver:~# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 2a4cf8552106 python:3.8 "/bin/bash" 2 hours ago Exited (137) 9 seconds ago flask_demo # 2.打包镜像 root@rionserver:~# docker commit -a 'AuthorName' -m "desc this app" flask_demo flask-image:v1 sha256:90d06fdcf87a669a47aea26183cce0ee9c67acaee92a49585ba4ef99f7d46042 root@rionserver:~# docker images REPOSITORY TAG IMAGE ID CREATED SIZE flask-image v1 90d06fdcf87a 52 seconds ago 923MB python 3.8 050b8443e26e 2 weeks ago 912MB
-
运行镜像
# 1.生成容器 root@rionserver:~# docker run -d -p 5000:5000 flask-image:v1 python /root/flask/app.py # 2.查看容器启动情况 docker ps -a root@rionserver:~# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 52edb3f3b628 flask-image:v1 "python /root/flask/…" 3 minutes ago Up 3 minutes 0.0.0.0:5000->5000/tcp, :::5000->5000/tcp flask_demo4 # 3.查看容器的详细启动信息 root@rionserver:~# docker inspect flask_demo4 ...... "Networks": { "bridge": { "IPAMConfig": null, "Links": null, "Aliases": null, "NetworkID": "ddff9289399998b325add56ea591ea704f7b337b8e590b9a5702cbceb00a60df", "EndpointID": "29836349733fb1dade1edcf4259b05fbf9fb4296043d2e009bf77f0b1f05fa7a", "Gateway": "172.17.0.1", "IPAddress": "172.17.0.2", ...... } }
-
访问 flask web服务
root@rionserver:~# curl http://172.17.0.2:5000 this is flask index! root@rionserver:~#