Docker

一、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)访问网址获取个人的加速器地址

1533622722178

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

1533623675145

4、Docker是怎么工作的

Docker是一个CS结构的系统,Docker的守护进程运行在主机上,客户端通过socket连接与守护进程进行传输命令,守护进程接受命令并管理运行在主机上的容器。

一个主机上可能有多个容器,每个中运行着镜像(tomcat、mysql...)的实例。

img

5、Docker为什么比虚拟机快

详情请见

虚拟机实现框架docker实现框架

(1)由上图可以看出Docker比虚拟机少了抽象层Hypervisor,Docker不需要Hypervisor来实现硬件资源虚拟化,而是直接采用宿主的硬件资源。

(2)而且Docker采用的是宿主机的内核,所以新建一个容器时不需要像虚拟机那样重新加载操作系统内核,从而避免引导、加载系统内核这个耗时的操作。

三、常用命令

1、帮助命令

$ docker --help

2、镜像命令

1)查看本地主机中的所有镜像

$ sudo docker images

	Option:
	  -a:列出本地所有镜像(包括中间映像层)**
	  -q:只显示镜像id**
	  --digests:显示镜像完整的描述信息
	  --no-trunc:不截断输出

1533634161051

同一个仓库源可以有多个tag,代表这个仓库源的不同版本,所以我们使用REPOSITORY:TAG来定义不同的镜像。

2)从hub上查找镜像

$ sudo docker search 查找镜像名
	
	Option:
	   --no-trunc:不截断输出
	   -s 数字:列出星星不小于指定值的镜像
	   --automated:列出自动构建类型的镜像

1533633562964

3)下载镜像

# 版本号默认为lastest,最新版本
$ sudo docker pull 下载的镜像名:[版本号]

1533633948374

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

启动交互式容器

1533627744155

2)列出Docker中有哪些容器在运行

$ sudo docker ps

	Option:
		-a:列出所有运行的容器(正在运行+历史运行)
		-l:显示最近创建的容器
		-n 数字:显示指定数字创建的容器
		-q:静默模式,只显示容器编号**
		--no-trunc:不截断输出

1533628054077

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

1533690548905

由上图发现,我们运行的容器已经退出。

这个是Docker机制的问题,由于我们启动的容器中没有前台进程,而是以后台进程的形式运行的,Docker就会以为它没事干,于是就将其杀死。

解决方案:

# 1.如果本地镜像只有一个版本,可以直接使用仓库源的名字
# 2.这句命令的含义是:运行一个容器,使用/bin/sh执行后面的shell脚本
$ sudo docker run -d centos /bin/sh -c "while true;do echo hello x5456;sleep 2;done"

1533694197017

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

1533691697043

9)拷贝容器中的文件到本地

$ sudo docker cp 容器id:容器中文件的位置 要copy到本地的位置

四、Docker镜像

镜像是一种轻量级、可执行的独立软件包,**用来打包软件运行环境和机基于运行环境开发的软件**,它包括某个软件所需要的所有内容(代码、库、环境变量、配置文件...)

1、UnionFS联合文件系统

联合文件系统是一种分层、轻量级、高性能的文件系统,它可以一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。

Docker的镜像基于UnionFS,也是由一层一层的文件系统组成。

就像我们拉镜像的时候,实际上下载了多层。

1533692670444

为啥tomcat会辣么大??

1533692774507

采用这种分层结构的好处

最大的一个好处就是--共享资源

比如:有多个进行都是从相同的A镜像构建而来,那么宿主机只需要在磁盘上保存一份A镜像,内存中只需要加载一份A镜像,就可以为所有容器服务了。

2、生成镜像Demo

1.从Hub上下载tomcat镜像到本地并运行

#                 对外暴露端口 内部使用端口
$ sudo docker run -it -p 8888:8080 tomcat

1533694709925

2.故意删除tomcat容器的文档

1533695118951

1533695072321

3.以当前运行的tomcat作为模板,提交生成新的镜像

$ sudo docker commit -a="作者" -m="描述信息" 容器id 要创建的镜像名:[标签名]
# eg.
$ sudo docker commit -a="x5456" -m="del tomcat docs" 70c6fc38df47 x5456/tomcat:2.0

4.启动我们生成的镜像

1533695613314

1533695579312

五、Docker的数据管理

部分参考于:这里

生产环境中使用Docker的过程中,容器中会产生数据,如果不通过commit命令生成一个新的镜像,当容器删除后,其中数据就没有了,所以我们往往需要**对数据进行持久化**,或者需要在**多个容器之间进行数据共享**,这必然涉及容器的数据管理操作。

容器中管理数据主要有两种方式:

  1. 数据卷(Data Volumes):容器内数据直接映射到本地主机环境;如何在容器内创建数据卷,并且把本地的目录或文件挂载到容器内的数据卷中。
  2. 数据卷容器(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 .

1533706308408

3.由于我们上面命令没有指定宿主机的位置,所以我们需要查看容器详细信息

$ sudo docker inspect 724f7b7a9793

1533706983968

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)每条指令都会创建一个新的镜像层,并对镜像进行提交

1533868028319

2、Docker执行Dockerfile的流程

1)Docker从基础镜像运行一个容器

2)执行一条指令就对容器进行修改

3)执行完一条指令就使用类似docker commit的操作提交一个新的镜像层

4)docker再基于刚刚提交的镜像运行一个新容器

由于镜像是由多个镜像层组成的,所以提交一个镜像层 <==> 生成了一个新镜像

5)继续执行下一条指令,直到所有指令都执行完毕

1533868603224

从应用软件的角度上来看,Dockerfile、Docker镜像与Docker容器分别代表软件的三个不同阶段

  • Dockerfile:软件原材料,面向开发
  • Docker镜像:软件的交付品
  • Docker容器:软件运行状态

1533869113643

3、Dockerfile的保留字指令

1)FROM

基础镜像,当前镜像是基于哪个镜像的

2)MAINTAINER

镜像维护者的姓名和邮箱地址

3)RUN

容器构建时需要运行的命令

1533869585666

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.创建镜像仓库

1533708554813

1533708642369

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:[镜像版本号]

1533709140661

$ 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.在阿里云上查看

1533709210050

Docker安装Oracle

原文地址:https://www.cnblogs.com/x54256/p/9541124.html