一、Docker简介
由于在项目部署的时候经常会出现在本机上运行是好使的,但是部署到服务器上时出现各种问题,而这种问题的原因经常是因为环境的问题,所以Docker出现了。
Docker 是基于Go语言实现的开源项目。
Docker是在Linux容器技术的基础上发展出来的。我们可以将应用运行在Docker容器上,而Docker容器在任何操作系统上都是一致的。
Docker主要通过对应用组件的封装、分发、部署、运行等进行管理,来实现用户的app及其运行环境能够做到**一次封装,到处运行**。
二、Docker的安装
1、Ubuntu安装Docker
$ sudo apt install docker.io
$ sudo systemctl start docker
$ sudo systemctl enable docker
# 查看是否安装成功
$ docker -v
>> Docker version 17.12.1-ce, build 7390fc6
2、配置阿里云镜像加速
1)访问网址获取个人的加速器地址
2)按照下面的操作文档进行操作
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://l7s5cnt9.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
3、hello,world
# 非管理员用户要加sudo
$ sudo docker run hello-world
4、Docker是怎么工作的
Docker是一个CS结构的系统,Docker的守护进程运行在主机上,客户端通过socket连接与守护进程进行传输命令,守护进程接受命令并管理运行在主机上的容器。
一个主机上可能有多个容器,每个中运行着镜像(tomcat、mysql...)的实例。
5、Docker为什么比虚拟机快
(1)由上图可以看出Docker比虚拟机少了抽象层Hypervisor,Docker不需要Hypervisor来实现硬件资源虚拟化,而是直接采用宿主的硬件资源。
(2)而且Docker采用的是宿主机的内核,所以新建一个容器时不需要像虚拟机那样重新加载操作系统内核,从而避免引导、加载系统内核这个耗时的操作。
三、常用命令
1、帮助命令
$ docker --help
2、镜像命令
1)查看本地主机中的所有镜像
$ sudo docker images
Option:
-a:列出本地所有镜像(包括中间映像层)**
-q:只显示镜像id**
--digests:显示镜像完整的描述信息
--no-trunc:不截断输出
同一个仓库源可以有多个tag,代表这个仓库源的不同版本,所以我们使用REPOSITORY:TAG来定义不同的镜像。
2)从hub上查找镜像
$ sudo docker search 查找镜像名
Option:
--no-trunc:不截断输出
-s 数字:列出星星不小于指定值的镜像
--automated:列出自动构建类型的镜像
3)下载镜像
# 版本号默认为lastest,最新版本
$ sudo docker pull 下载的镜像名:[版本号]
4)删除镜像
$ sudo docker rmi 某个镜像的id
# 强制删除,当镜像被某个容器使用时,无法被删除
$ sudo docker rmi -f 某个镜像的id
# 删除多个镜像
$ sudo docker rmi 镜像id1 镜像id2...
# 删除全部镜像
$ sudo docker rmi -f $(docker images -qa) # 查出本机所有镜像的id
3、容器命令
1)新建并启动容器
$ sudo docker run 镜像id
Option:
--name="想要给容器起的名字":设置容器名(可以不用写,会自动生成)
-d:在后台运行容器,也称守护式容器**
-i:以交互式运行容器,通常与-t同时使用**
-t:为容器分配一个伪终端,常与-i同时使用**
-P:随机端口映射
-p:指定端口映射,主要有以下4种格式
ip:hostPort:containerPort
ip::containerPort
hostPort:containerPort**
containerPort
启动交互式容器
2)列出Docker中有哪些容器在运行
$ sudo docker ps
Option:
-a:列出所有运行的容器(正在运行+历史运行)
-l:显示最近创建的容器
-n 数字:显示指定数字创建的容器
-q:静默模式,只显示容器编号**
--no-trunc:不截断输出
3)退出交互式容器
# 容器停止退出
exit
# 容器不停止退出
Ctrl+P+Q
4)其他操作
# 启动容器,将已经停止的容器启动
$ sudo docker start 容器id
# 重启容器
$ sudo docker restart 容器id
# 停止容器
$ sudo docker stop 容器id
# 强制停止容器
$ sudo docker kill 容器id
# 删除已经停止的容器
$ sudo docker rm 容器id
# 强制删除所有容器(不管是否停止)
$ sudo docker rm -f $(docker ps -aq)
$ sudo docker ps -aq | xargs docker rm
5)守护式启动
# 上面说过了,使用-d命令启动,下面介绍注意点
$ sudo docker run -d 镜像id
由上图发现,我们运行的容器已经退出。
这个是Docker机制的问题,由于我们启动的容器中没有前台进程,而是以后台进程的形式运行的,Docker就会以为它没事干,于是就将其杀死。
解决方案:
# 1.如果本地镜像只有一个版本,可以直接使用仓库源的名字
# 2.这句命令的含义是:运行一个容器,使用/bin/sh执行后面的shell脚本
$ sudo docker run -d centos /bin/sh -c "while true;do echo hello x5456;sleep 2;done"
6)查看容器日志
查看容器内运行的进程
$ sudo docker logs 容器编号
Option:
-t:加入时间戳
-f:跟随最新的日志打印
--tail 数字:显示指定数字内些条
7)查看容器内部细节
# 以json格式进行显示
$ sudo docker inspect 容器id
8)进入正在运行的容器并以命令行交互
# 容器中启动新的终端并执行命令,返回
# 如果不写后面的shell脚本,则会启动新的终端
$ sudo docker exec -it 容器id shell脚本
# 直接进入容器,不启动新的终端
$ sudo docker attach 容器id
9)拷贝容器中的文件到本地
$ sudo docker cp 容器id:容器中文件的位置 要copy到本地的位置
四、Docker镜像
镜像是一种轻量级、可执行的独立软件包,**用来打包软件运行环境和机基于运行环境开发的软件**,它包括某个软件所需要的所有内容(代码、库、环境变量、配置文件...)
1、UnionFS联合文件系统
联合文件系统是一种分层、轻量级、高性能的文件系统,它可以一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。
Docker的镜像基于UnionFS,也是由一层一层的文件系统组成。
就像我们拉镜像的时候,实际上下载了多层。
为啥tomcat会辣么大??
采用这种分层结构的好处
最大的一个好处就是--共享资源
比如:有多个进行都是从相同的A镜像构建而来,那么宿主机只需要在磁盘上保存一份A镜像,内存中只需要加载一份A镜像,就可以为所有容器服务了。
2、生成镜像Demo
1.从Hub上下载tomcat镜像到本地并运行
# 对外暴露端口 内部使用端口
$ sudo docker run -it -p 8888:8080 tomcat
2.故意删除tomcat容器的文档
3.以当前运行的tomcat作为模板,提交生成新的镜像
$ sudo docker commit -a="作者" -m="描述信息" 容器id 要创建的镜像名:[标签名]
# eg.
$ sudo docker commit -a="x5456" -m="del tomcat docs" 70c6fc38df47 x5456/tomcat:2.0
4.启动我们生成的镜像
五、Docker的数据管理
部分参考于:这里
生产环境中使用Docker的过程中,容器中会产生数据,如果不通过commit命令生成一个新的镜像,当容器删除后,其中数据就没有了,所以我们往往需要**对数据进行持久化**,或者需要在**多个容器之间进行数据共享**,这必然涉及容器的数据管理操作。
容器中管理数据主要有两种方式:
- 数据卷(Data Volumes):容器内数据直接映射到本地主机环境;如何在容器内创建数据卷,并且把本地的目录或文件挂载到容器内的数据卷中。
- 数据卷容器(Data Volume Containers):使用特定容器维护数据卷。如何使用数据卷容器在容器和主机、容器和容器之间共享数据,并实现数据的备份和恢复。
1、数据卷
可以用于同步代码
1)使用命令添加
$ sudo docker run -v 宿主机绝对路径:容器内目录 镜像id/镜像名
# 这样宿主机和容器中的这两个目录就联系起来了
$ sudo docker run -v /myData:/ContainerData centos
# 可以在目录后面加上:ro表示只读,这样有:ro的内个目录就只有read权限
$ sudo docker run -v /myData:/ContainerData:ro centos
2)采用DockerFile进行添加
1.书写DockerFile文件dockerfile2
FROM centos
VOLUME ["/dataVolumeContainer1","/dataVolumeContainer2"]
CMD echo "finished,--------success1"
CMD /bin/bash
2.使用命令生成镜像
$ sudo docker build -f dockerfile2 -t x5456/centos .
3.由于我们上面命令没有指定宿主机的位置,所以我们需要查看容器详细信息
$ sudo docker inspect 724f7b7a9793
2、数据卷容器
如果用户需要在**多个容器之间共享一些持续更新的数据**,最简单的方式是使用数据卷容器。数据卷容器也是一个容器,但是它的目的是专门用来提供数据卷供其他容器挂载。
1.创建一个数据卷容器dbdata,并在其中创建一个数据卷挂载到/dbdata:
$ docker run -it -v /dbdata --name dbdata centos
root@3ed94f279b6f:/#
2.查看/dbdata目录:
root@3ed94f279b6f:/# ls
bin boot **dbdata** dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
3.在其他容器中使用--volumes-from来挂载dbdata容器中的数据卷.
例如创建db1和db2两个容器,并从dbdata容器挂载数据卷:
$ docker run -it --volumes-from dbdata --name db1 ubuntu
$ docker run -it --volumes-from dbdata --name db2 ubuntu
此时,容器db1和db2都挂载同一个数据卷到相同的/dbdata目录。三个容器任何一方在该目录下的写入,其他容器都可以看到。
例如,在dbdata容器中创建一个test文件,如下所示:
root@3ed94f279b6f:/# cd /dbdata
root@3ed94f279b6f:/dbdata# touch test
root@3ed94f279b6f:/dbdata# ls
test
在db1容器内查看它:
$ docker run -it --volumes-from dbdata --name db1 ubuntu
root@4128d2d804b4:/# ls
bin boot dbdata dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
root@4128d2d804b4:/# ls dbdata/
test
4.数据卷的生命周期一直会持续到没有容器使用他时
六、Dockerfile
Dockerfile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本。
1、Dockerfile基础知识:
1)每条保留字指令都必须是大写字母且后面要跟随至少一个参数
2)指令从上到下顺序执行
3)#表示注释
4)每条指令都会创建一个新的镜像层,并对镜像进行提交
2、Docker执行Dockerfile的流程
1)Docker从基础镜像运行一个容器
2)执行一条指令就对容器进行修改
3)执行完一条指令就使用类似docker commit的操作提交一个新的镜像层
4)docker再基于刚刚提交的镜像运行一个新容器
由于镜像是由多个镜像层组成的,所以提交一个镜像层 <==> 生成了一个新镜像
5)继续执行下一条指令,直到所有指令都执行完毕
从应用软件的角度上来看,Dockerfile、Docker镜像与Docker容器分别代表软件的三个不同阶段
- Dockerfile:软件原材料,面向开发
- Docker镜像:软件的交付品
- Docker容器:软件运行状态
3、Dockerfile的保留字指令
1)FROM
基础镜像,当前镜像是基于哪个镜像的
2)MAINTAINER
镜像维护者的姓名和邮箱地址
3)RUN
容器构建时需要运行的命令
4)EXPOSE
容器对外暴露的端口
5)WORKDIR
指定创建容器后,终端默认登陆进来的工作目录
6)ENV
在构建镜像过程中设置环境变量
eg:
# 声明一个环境变量,这个变量可以在后续的任何指令中使用
ENV MY_PATH /usr/test
# 比如设置工作目录
WORKDIR $MY_PATH
7)ADD
将宿主机目录下的文件copy进镜像,而且ADD命令会自动处理URL和解压压缩包
8)COPY
将文件copy到镜像中
9)VOLUME
容器数据卷,用于数据的保存和持久化工作
10)CMD
指定容器启动时要运行的命令
- Dockerfile中可以有多个CMD指令,但只有最后一个生效,CMD会被docker run之后的参数替换
- 类似docker run /bin/sh xxx这种
11)ENTRYPOINT
指定容器启动时要运行的命令
* ENTRYPOINT会==追加==docker run之后的参数
12)ONBUILD
当构建一个被继承的Dockerfile时运行的命令,父镜像在被子镜像继承后触发这个命令
七、将镜像发布到阿里云上
1.创建镜像仓库
2.将镜像推送到阿里云上
$ sudo docker login --username=1203901753@qq.com registry.cn-hangzhou.aliyuncs.com
# 本地镜像id 想要在阿里云上显示的版本号
$ sudo docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/x5456/centos:[镜像版本号]
$ sudo docker push registry.cn-hangzhou.aliyuncs.com/x5456/centos:[镜像版本号]
$ sudo docker login --username=1203901753@qq.com registry.cn-hangzhou.aliyuncs.com
# 本地镜像id 想要在阿里云上显示的版本号
$ sudo docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/x5456/springboot:[镜像版本号]
$ sudo docker push registry.cn-hangzhou.aliyuncs.com/x5456/springboot:[镜像版本号]
3.在阿里云上查看