Docker的学习
Docker与传统虚拟化
虚拟机就是在操作系统里面运行另一种操作系统,虚拟机看上去和真实系统一模一样,对于应用程序而言无感知。对于宿主机而言,虚拟机就是一个普通文件,不需要就可以删掉,对于其他部分毫无影响。虚拟机直接使用宿主机硬件资源,所以虚拟机的缺点就是:
- 资源占用多
- 冗余步骤多
- 启动慢
常用的虚拟机软件:VMware,Virtualbox
由于虚拟机存在着一些问题,Linux发展出了另一种虚拟化技术:Linux容器(Linux Containers,缩写LXC),Linux容器不是模拟一个完整的操作系统,而是对进程进行隔离,对Kernel内核,库等进行共享。有了容器,就可以将软件运行所需要的资源打包到一个个隔离的容器中。这样就使得系统变得高效轻盈,并保证所有环境中的软件都能始终如一地运行
而Docker正是基于容器虚拟化技术,使用go语言开发的。Docker和传统的虚拟机方式不同之处在于:
- 传统虚拟机技术是虚拟出一套硬件后,在其上面运行一个完整的操作系统,在该操作系统上再运行所需的应用进程
- 而容器内应用进程直接运行在宿主机的内核,容器没有自己的内核,而且也没有进行硬件虚拟化。因此容器要比虚拟机更加轻便
- 每个容器之间互相隔离,每个容器都有自己的文件系统,容器之间不会互相影响
Docker中的几个概念
Docker本身是一个容器运行载体或称之为管理引擎。我们把应用程序和配置依赖打包好形成一个可交付的运行环境,这个运行环境就是image镜像文件。只有通过镜像文件才可以生成Docker容器。image文件可以看作容器的模板,Docker根据image文件生成容器实例。同一个image文件,可以生成多个同时运行的容器实例
镜像:根据image生成容器实例,其本身也是一个文件
容器:根据镜像创建的实例,一个容器运行一个服务,当我们需要的时候,自己通过docker客户端就可以创建对应的实例,每个实例之间互不影响
仓库:就是存放一堆镜像的地方,我们可以将镜像发布到仓库中,需要的时候也可以从仓库拉下来
对Docker镜像加深理解
Docker镜像都是只读的,采用UnionFS(联合文件系统),采用分层的镜像结构,一层套着一层,Docker镜像采用这种分层结构,主要是为了资源共享
Docker的安装与卸载
安装
这里基于Centos7进行安装,实际上官网介绍的也足够详细,这里只是把命令记录下
# 0.查看Centos版本
cat /etc/redhot-release
# 1.卸载原有的docker或docker-engine 如果没有安装过可以忽略
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
# 2.安装yum-utils以及配置仓库(因为docker仓库比较慢, 这里替换成阿里云的仓库)
sudo yum install -y yum-utils
# 3.安装最新版本的Docker引擎
sudo yum install docker-ce docker-ce-cli containerd.io
# 4.验证docker是否安装成功
docker version
# 5.设置阿里云镜像加速
vim /etc/docker/daemon.json
# 在该文件中加入如下配置,docker这里是用json作为配置文件
{
"registry-mirrors": ["https://i5ct9lf7.mirror.aliyuncs.com"]
}
# 6.重启docker
sudo systemctl daemon-reload
sudo systemctl restart docker
如果当前用户有root权限,可以忽略sudo
更详细的仓库镜像加速可以参看:Docker教程,这个教程非常详细,值得收藏与学习
卸载
# 1.卸载docker引擎
sudo yum remove docker-ce docker-ce-cli containerd.io
# 2.删除镜像,容器,数据卷和配置文件
sudo rm -rf /var/lib/docker
sudo rm -rf /var/lib/containerd
Docker命令
Docker帮助命令
1.查看docker版本
docker version
2.docker相关信息,比version命令显示的信息更加全面些
docker info
3.docker帮助命令
docker --help
Docker镜像相关命令
1.列出本地的镜像
docker images [options]
options参数说明
-a:列出本地所有镜像
-q:只显示镜像id
--digests:显示镜像的摘要信息
--no-trunc:显示完整的进行信息
对于options选项说明:注意有的是一个减号,有些是两个减号
输入docker images后会列出镜像列表,这个列表有几个选项,各个选项说明如下:
REPOSITORY:表示镜像的仓库源
TAG:镜像的版本标签
IMAGE ID:镜像创建时间
SIZE:镜像大小
同一个仓库源可以有多个TAG,代表这个仓库中不同的版本,我们使用 REPOSITORY:TAG来定义不同的镜像
如果不指定一个镜像的版本标签,默认将拉取latest最新版
2.搜索镜像
docker search [options] 镜像名称
options参数说明
--no-trunc:显示完整的镜像描述
-s:列出收藏数不小于指定值的镜像
--automated:只列出automated build类型的镜像
其中有的镜像会显示OFFICIAL=OK,表示官方版本
3.下载镜像
docker pull 镜像名称[:TAG]
默认是latest最新镜像
4.删除镜像
docker rmi 镜像名/镜像ID
删除单个:docker rmi -f 镜像ID
删除多个:docker rmi -f 镜像名1:TAG 镜像名2:TAG
删除全部:docker rmi -f $(docker images -qa) 先通过images -qa命令查询出所有的镜像ID,再通过这些ID删除
5.查看镜像创建历史
docker history 镜像名/镜像ID
Docker容器相关命令
只有先下载有镜像,再根据镜像创建容器
1.创建并启动容器
docker run [options] IMAGE [command] [arg...]
options参数说明
--name="容器新名称":为容器指定一个名称
-d:很重要的参数,后台运行容器,并返回容器ID,也即启动守护式容器
-i:以交互模式运行容器,同样与-t同时使用
-t:为容器重新分配一个输入终端,通常与-i同时使用
-P:随机端口映射
-p:很重要的参数,指定端口映射 docker端口:容器端口
比较常用的方式:
在docker中交互式运行centos镜像,会直接进入容器内部并打开终端
docker run -it centos
后台运行tomcat8.5 并映射端口
docker run -d -p 8080:8080 tomcat:8.5
注意:当我们使用-p参数映射端口时,可能会出现docker: Error response from daemon: driver failed programming external connectivity,目前找到的解决办法就是重启Docker:systemctl restart docker,可以参考博客
2.列出当前所有正在运行的容器
docker ps [options]
options参数说明
-a:列出当前所有正在运行的容器+历史上运行过的
-l:显示最近创建的容器
-n:显示最近n个创建的容器
-q:只显示容器ID
--no-trunc:显示完整的容器描述
3.退出容器
当使用交互式run启动容器后,有两种退出方式
exit:退出后,容器会直接停止退出
ctrl+P+Q:推出后,容器不停止退出
4.启动容器
docker start 容器名/容器ID
5.重启容器
docker restart 容器名/容器ID
6.停止容器
docker stop 容器名/容器ID
7.强制停止容器
docker kill 容器名/容器ID
8.删除已停止的容器
docker rm 容器名/容器ID
一次性删除多个容器
docker rm -f $(docker ps -qa)
-f:表示直接删除,即使运行中的容器也可以删除
9.查看容器日志
docker logs -f -t --tail 容器ID
10.查看容器内运行的进程
docker top 容器ID
11.查看容器内部细节(很重要)
docker inspect 容器ID
这个命令很重要,可以看到docker容器的配置细节
12.进入正在运行的容器并以命令行交互
1.attach
docker attach 容器ID
2.exec
docker exec -it 容器ID 需要执行的参数命令行(如 /bin/bash)
这两个命令区别就在于
attach命令输入exit后退出容器会直接导致容器container的停止
而使用docker exec输入exit不会导致容器停止,所以exec命令更加常用些
13.拷贝文件到宿主机上
docker cp 容器ID:容器内路径 宿主机路径
注意:容器ID后有个冒号: 不要忘记
14.提交容器副本使之成为本地的一个新镜像
docker commit -m="提交的描述信息" -a="作者" 容器ID 新镜像名[:TAG]
15.提交镜像到镜像仓库
docker push [options] 镜像名[:TAG]
options参数说明
--disable-content-trust:忽略镜像的校验,默认开启
16.根据Dockerfile文件自定义构建镜像
docker -f /mydocker/Dockerfile -t my/centos[:TAG] .
-f:指定Dockerfile文件路径
-t:新构建出的镜像名称
最后还有一个.点符号不要忘记,表示当前目录
如果不指定TAG就表示是latest最新版
关于DockerFile文件编写在下面章节记录
Docker容器数据卷
数据卷就是将宿主机的一个或多个目录与Docker容器关联起来,用以实现二者之间数据共享
命令
就是在docker run命令后加上-v参数
docker run -it -v 宿主机绝对路径:容器内绝对路径 镜像名/镜像ID
-it:已交互式运行容器, 在上面Docker运行命令有解释过
-v:实际上就是volume(容积,体积)的简写,可以使用多次-v挂载多个数据卷
如果路径不存在会自动创建路径
注意:两个路径之间的:冒号不能省略
如果需要创建只读容器,也就是说容器可以正常同步文件以及读操作,但是不能写,宿主机路径可读可写,需要加上:ro(read only)命令
docker run -it -v 宿主机绝对路径:容器内绝对路径:ro 镜像名/镜像ID
少数情况下Docker挂载宿主机目录会出现cannot open directory.: Permission denied权限不足的问题,解决方法就是在挂载目录后面多加一个--privileged=true
参数即可
docker run -it -v 宿主机绝对路径:容器内绝对路径 镜像名/镜像ID --privilaged=true
查看数据卷是否配置好就通过docker inspect 容器ID
命令就可以看到,输出的信息中有关于volume的描述
Docker容器间传递共享数据卷
一个容器可以共享一个已经运行中容器的数据卷,这两个容器类似于继承的关系,但又不相同,将其看作为多个容器之间共享数据卷目录比较合适
运行一个容器
docker run -it -v /myDataVolume:/dataVolumeContainer --name dc01 centos
再运行一个容器共享dc01容器的数据卷
docker run -it --name dc02 --volumes-from dc01 centos
这样dc01和dc03容器就共享/myDataVolume:/dataVolumeContainer
这个数据卷关系,任何文件的增删改,这两个容器都可以感知到
注意:即使dc01容器被删除,数据卷也存在,dc03容器还是可以正常使用。也就是说容器之间配置信息的传递,数据卷的生命周期一直持续到没有相关容器才停止
Dockerfile文件
Dockerfile文件是用来构建Docker 镜像的构建文件,是由一系列命令和参数构成的脚本,有一定的语法结构,基于现有镜像进行定制或修改形成新的自定义镜像
构建三步骤
- 编写Dockerfile文件
- docker build 命令根据Dockerfile文件构建镜像
- docker run 命令运行镜像
Dockerfile内容基础知识
- 每个关键字指令都必须大写并且都要根据至少一个参数
- 指令从上到下顺序执行
#
表示注释- 每条指令都会创建一个新的镜像层,并会对镜像进行commit提交
根据Dockerfile构建镜像大致流程
- docker从基础镜像运行一个容器
- 执行一条指令并对容器进行修改
- 执行类似docker commit 的操作提交一个新的镜像层
- docker再基于刚才提交的镜像运行一个新容器(UnionFS-联合文件系统,一层包着一层)
- 执行dockerfile的下一条指令直到所有的指令都执行完成
关键字指令
FROM
基础镜像,当前新镜像是根据哪个进行进行修改的
MAINTAINER
镜像维护者的姓名和邮箱地址
RUN
容器构建时需要运行的Linux命令
EXPOSE
当前容器对外暴露的端口
WORKDIR
指定再创建容器后,通过docker run -it 终端登录进来的工作目录,一个落脚点
ENV
用来在构建镜像过程中设置环境变量供上下文使用
ADD
将宿主机目录下的文件拷贝进镜像并且ADD命令会自动处理URL和解压tar压缩包
ADD src dest
COPY
类似于ADD,拷贝文件和目录到镜像中,注意与ADD指令的区别,ADD会自动解压tar压缩包,而COPY不会,所以ADD更为强大些
COPY src dest
VOLUME
容器数据卷,用于数据保存持久化和共享工作
CMD
指定一个容器启动时要运行的命令,可以有多个CMD指令,但是只有最后一个生效,还需要注意的是CMD会被docker run命令后带的参数替换
ENTRYPOINT
指定一个容器启动时需要运行的命令,目的和CMD一样
注意与CMD指令区别,多个CMD指令只有最后一个生效,而多个ENTRYPOINT都会生效,docker run后带着个参数可以替换CMD,实际上是run后的参数会自动追加CMD到最后,多个CMD只有最后一个会生效所以就替换了,而对于ENTRYPOINT来说也是追加命令,但是多条ENTRYPOINT都会生效
ONBUILD
当一个Dockerfile文件被构建时,其FROM指令依赖镜像的Dockerfile如果有这个指令,则父镜像的ONBUILD会被触发
Dockerfile指令分类图
常见软件容器安装
这里参考Docker教程即可,非常详细
这里记录下如下两个命令:
1.备份mysql数据
docker exec mysql容器ID sh -c 'exec mysqldump --all-databases -uroot -p"root"' > /tmp/all-database-bak.sql
2.运行redis
docker run -p 6379:6379 -v /myredis/data:/data -v /myredis/conf/redis.conf:/usr/local/etc/redis/redis.conf -d redis:3.2 redis-server /usr/local/etc/redis/redis.conf --appendonly yes
redis-server /usr/local/etc/redis/redis.conf
:根据这个redis配置文件启动redis
--appendonly yes
:开启AOF
推送到阿里云Dockers仓库
1.登录到仓库
sudo docker login --username=xxx registry.cn-hangzhou.aliyuncs.com
用户名就是阿里云账号全名,接下来会让输入密码,密码就是开通服务时设置的密码
2.给镜像标记TAG
sudo docker tag [ImageId] redistry.cn-hangzhou.aliyuncs.com/名称空间/镜像名[:镜像版本号]
3.推送镜像到registry
sudo docker push registry.cn-hangzhou.aliyuncs.com/名称空间/镜像名[:镜像版本号]
push后部分镜像名称需要与docker tag后面填写镜像名称一致