Docker之容器

1、容器

 

 

 

2、容器相关命令

2.1、运行容器(docker run)

通过 docker run [options] image 命令来运行一个容器。

options 参数说明:

  • -i:以交互形式运行容器。通常与 -t 同时使用。
  • -t:为容器重新分配一个伪输入终端。
  • --name:为运行的容器指定名称。如果不指定名称,docker会为该容器随机指定一个名称。比如:docker run -it --name mytomcat tomcat

 

下面运行 centos 容器:

执行运行命令之后,可以看到 root 后面是容器的 id,此时说明 centos 容器已经启动成功,并且此时是进入了该容器的输入终端中。

 

2.1.1、启动容器(docker start)

我们可以先通过 docker ps -a 命令来查看所有正在运行和之前运行过的容器,然后通过 docker start 容器ID 的命令来启动已停止的容器。

使用示例:

 

2.1.2、重启容器(docker restart)

正在运行的容器或者已经停止的容器都可以通过 docker restart 容器ID 命令来重启容器。

使用示例:

 

2.1.3、以后台形式运行容器(docker run -d)

 -d 参数意思是以后台模式启动容器。

通过该参数运行容器,你会发现有些容器会自动退出。因为 docker 容器运行必须要有一个前台进程,否则容器会自动退出,这个是 docker 的机制问题。

下面运行 centos 容器,运行过后通过 docker ps -a 命令可以发现已经自动退出了:

 

所以一般可以用 -d 参数时搭配 -it 参数一起使用,此时在运行容器时不会自动进入容器,但是容器也不会自动退出。

但是有些容器也不会自动退出,比如后台运行 tomcat 容器。

 

2.1.4、指定访问容器内网络的端口(docker run -p)

容器中可以运行一些网络应用,要想让外部也可以访问容器内运行的应用,可以通过 -P(随机映射端口) 或 -p (指定端口) 参数来指定端口映射。

(1)当使用 -P 标记时,Docker 会随机映射一个 49000~49900 的端口到内部容器开放的网络端口。

 比如:通过 docker run -it -P tomcat 我们运行一个 tomcat:

上面我们可以看到宿主机的 49154 端口映射到了 tomcat 的 8080 端口,此时我们通过访问 宿主机ip:49154 可以看到 tomcat 的默认项目的首页,或者可以直接在宿主机即虚拟机上通过访问 localhost:49154 访问 tomcat 的首页。

访问报 404 可参考:https://www.cnblogs.com/wenxuehai/p/15154703.html#_label0_0

 

(2)-p(小写)则可以指定要映射的IP和端口,但是在一个指定端口上只可以绑定一个容器。

语法格式:

docker run -p 宿主机端口:容器端口 镜像

实例使用:比如我们运行 tomcat 容器,并且将本地宿主机的 8888 端口映射到容器上的 8080 端口(tomcat的默认端口都是8080)。

 

此时正常情况下我们通过访问宿主主机的 ip:8888 即可访问到 tomcat 的默认页面:

 

访问如果报 404 可参考:https://www.cnblogs.com/wenxuehai/p/15154703.html#_label0_0 

 

2.2、停止容器(exit、docker stop、docker kill)

如果我们进入了容器的终端,此时可以直接通过 exit 命令来退出并停止容器。exit 命令在退出容器的同时也关闭容器,进入docker容器后如果退出容器,容器就会变成 Exited 的状态。

或者直接通过 ctrl+P+Q 快捷键来控制容器不停止只退出。

 

通过 stop 和 kill 命令也能关闭容器:

docker stop 容器id   #正常关闭容器
docker kill 容器id     #暴力关闭容器

 

2.3、查看运行的容器列表(docker ps)

可以通过 docker ps 命令来查看所有运行的容器。

docker ps   # 查看当前正在运行的容器
docker ps -a  # 查看当前运行和所有运行过的容器
docker ps -l #查看上一个运行的容器

示例如下:

可以看到查询结果的列名中,CONTAINER ID 就是容器的 id,IMAGE 就是镜像名称,status 表示容器的状态(exited表示已经退出停止,up表示正在运行),NAMES 就是容器的名称。 

 

2.4、重新进入容器(docker attach、docker exec)

在我们使用 -itd 命令来以后台模式运行容器,或者是在运行容器时使用 ctrl + P +Q 来退出容器但不停止容器时,此时我们可以通过 docker attach 或者是 docker exec 命令来重新进入容器。

 

2.4.1、docker exec(推荐使用)

docker exec 命令可以在宿主机外直接对容器进行操作,当然也可以进入容器的终端。

如果从 exec 命令进入容器,然后退出容器的话,容器不会停止,所以一般推荐大家使用 docker exec 命令。

 

2.4.2、docker attach(进入后退出会导致容器停止)

docker attach 命令会直接进入该容器的终端中,并且如果从该命令进入,然后退出容器的话会导致容器停止。如下执行完 attach 命令后,可以看到终端名称发生了改变:

 

2.5、删除容器(docker rm)

docker rm 容器ID  #删除已停止运行的容器。如果该容器正在运行,可能会提示报错
docker rm -f 容器ID  #强制删除容器,可删除正在运行的容器。实际上就是先停止后删除

使用示例:

 

2.6、查看容器日志(docker logs)

通过 docker logs 容器ID 命令可查看容器日志。通过加参数  docker logs -t -f 容器ID 可保持一直输出容器最新日志在控制台。

 

2.7、查看容器内运行的进程(docker top 容器id)

通过 docker top 容器id 命令可查看该容器内运行的进程:

 

2.8、查看容器内部细节(docker inspect 容器id)

通过 docker inspect 容器id 命令可查看该容器内部细节,可以看到是一个 json 格式数据:

 

2.9、复制容器内文件到宿主机(docker cp )

可通过 cp 命令将容器内的文件复制到本宿主机上来,语法如下:

docker cp 容器ID:容器内的绝对路径 本宿主机路径

#示例:
docker cp f429600985ba:/usr/aa.log /root

 

3、容器数据卷

3.1、容器数据卷基本介绍

当我们在使用 docker 容器的时候,会产生一系列的数据文件,这些数据文件在我们关闭 docker 容器后是会消失的。如果我们希望在 docker 容器运行过程中产生的部分数据保持持久化,我们可以使用数据卷。并且数据卷在容器之间是可以数据共享。

通俗地来说,docker 容器数据卷可以看成使我们生活中常用的u盘,它存在于一个或多个的容器中,由 docker 挂载到容器,但不属于联合文件系统,Docker 不会在容器删除时删除其挂载的数据卷。

特点:

  1. 数据卷可以在容器之间共享或重用数据。
  2. 数据卷中的更改可以直接生效。
  3. 数据卷中的更改不会包含在镜像的更新中。
  4. 数据卷的生命周期一直持续到没有容器使用它为止。

数据卷呈现给Docker容器的形式就是一个目录,支持多个容器间共享,修改也不会影响镜像。

 

添加数据卷的方式有两种,第一种是直接通过命令行挂载,第二种是通过 dockerFile 添加:

3.2、命令行创建数据卷(docker run -it -v)

语法格式:

docker run -it -v  宿主机目录的绝对路径:容器内目录的绝对路径 镜像名   #即运行一个容器,并将本地主机的一个指定目录当做数据卷挂载在该容器上。-v:v是volume的缩写

上面命令把一个本地主机的目录当做数据卷挂载在容器上,如果上面指定的宿主机的目录或者容器内的目录不存在,则 docker 会自动创建该目录。

实现了数据卷挂载之后,本地主机和容器指定的目录之间就会实现数据共享。在主机或者容器上指定的目录进行一系列的操作,这些操作都会同步到另一方。比如在容器内新建文件或者修改文件,则主机上对应的目录下也会新建文件或者文件内容会被自动修改。

在挂载之后,即使容器停止了,宿主机上对数据卷做的内容修改还是会同步到容器内。(容器停止后,我们可以通过 docker ps -a 命令找到停止的容器,并且重新启动该容器,就可以看到宿主机内在指定目录进行的修改仍然会同步到该容器内指定的目录下)

 

使用实例:

下面我们运行一个 centos 容器,并将主机内的某个目录当做数据卷挂载在容器上:

 

上面可以看到,主机内的 /usr 目录下一开始并没有我们指定的 myData 目录,我们在挂载了数据卷后重新查看 /usr 目录下的文件,可以看到自动创建该目录:

 

我们在主机或者容器上指定的目录进行一系列的操作,你会发现,这些操作会同步到另一方。比如在容器内新建文件或者修改文件,则主机上对应的目录下也会新建文件或者文件内容会被自动修改:

   

 

3.2.1、限制容器不能修改数据卷文件

我们在挂载的时候可以给数据卷加上权限,即限制容器内不能修改新增文件。只能宿主机单向地给数据卷添加修改内容,容器内新增或者修改文件内容都不会被允许,容器内只能查看文件。

docker run -it -v 宿主机目录的绝对路径:容器内目录的绝对路径:ro 镜像名   #ro:意思是read only

 

 3.2.2、查看数据卷挂载是否成功

如果我们不知道数据卷是否挂载成功时,我们可以通过 docker inspect 容器ID 命令来检查数据卷的挂载结果。

上面的命令可以查看容器的详细情况,命令返回的是JSON格式的字符串,运行命令之后我们在返回的JSON字符串中的 hostconfig.binds 属性中可以看到在挂载时输入的命令参数 (/宿主机绝对路径目录: /容器内目录 ):

有时候在 hostconfig.binds 属性中并不能看到挂载的目录,此时我们可以通过以下命令来查看挂载的目录。如下:

docker inspect 容器id | grep Mounts -A 20

输出的信息中 Source 指的是宿主机的目录,Destination 指的是容器内的目录。

 

3.3、通过Dockerfile创建数据卷

我们可以通过 dockerfile 来定义创建一个镜像时的指令,在这些指令里面指定该镜像的数据卷。

使用示例:

我们在 /usr/dockerData/ 目录下新建一个名为 Dockerfile 的文件,并将以下指令内容编写进该文件:

FROM centos

VOLUME ["/myContainerData1","/myContainerData2"]

CMD echo "build success............."

CMD /bin/bash

可以看到,上面我们指定容器内的两个数据卷目录。我们并没有用 -v 命令来指定宿主机的数据卷目录,这是因为 docker 考虑到宿主机目录是依赖于特定的宿主机的,并不能保证所有的宿主机都存在这样特定的目录。因为没有指定宿主机内数据卷的目录,所以 docker 会为宿主机指定一个目录作为数据卷的目录。

执行结果:

 

然后就可以通过 dokcer build 命令来通过该 Dockerfile 文件来构建一个新的镜像。语法结构如下:

docker build -f dockerfile文件的完整绝对路径 -t 命名空间/镜像名 .   #最后的 . 代表本次执行的上下文路径,不要漏掉无法构建成功

执行结果如下,执行过后可以看到本地就生成了一个新的镜像:

 

通过跑该镜像运行一个容器,然后进入该容器的目录,可以看到根目录下生成了两个我们指定的数据卷的目录:

通过 docker inspect 容器ID 命令查看容器信息,在 mounts.source 属性中可以看到 docker 指定的宿主机内的数据卷目录,该目录和容器内指定的目录是共享的。

 

 

 

3.3.1、出现cannot open directory问题

Docker挂载主机目录Docker访问出现cannot open directory :: Permission denied

解决办法:在挂载目录居多加一个-privileged=true参数即可,即最终 dockerfile 文件内容如下:

FROM centos

VOLUME ["/myContainerData1","/myContainerData2"] --privileged=true

CMD echo "build success............."

CMD /bin/bash

 

3.4、数据卷容器(容器数据共享)

命名的容器挂载数据卷,其他的容器通过挂载这个父容器实现数据共享,挂载数据卷的容器,我们称为数据卷容器。也就是说当一个容器挂载了数据卷,其他容器可以通过挂载(类似于继承)这个容器的方式来实现共享这个数据卷的数据。

首先,我们建立父容器

docker run -it --name parentContainer 镜像名   #我们通过具有挂载数据卷指令的dockerFile建立的镜像来运行容器

上面通过一个具有挂载数据卷指令的 dockerfile 建立的镜像来运行容器,该容器就挂载了一个指定的数据卷。

然后我们就可以 --volumes -from 命令来通过继承父容器,以此可以建立多个子容器:

docker run -it --name sonContainer1 --volumes-from parentContainer 镜像名

docker run -it --name sonContainer2 --volumes-from parentContainer 镜像名

建立的这些子容器和父容器共享数据卷,当在宿主机或者是父容器或者是子容器的数据卷指定目录下新增修改文件,对应的其他地方的指定目录下的文件都会被同时修改。

容器之间配置信息的传递,数据卷的生命周期会一致持续到没有容器使用它为止,换言之,只要有一个容器仍在使用该数据卷,该数据卷一直都可以进行数据共享。假设我们把父容器停止运行,两个字容器之间依旧可以进行数据共享,而且通过继承子容器生成的新容器,一样可以与子容器进行数据共享,这就是docker容器间的数据传递共享。

 

posted @ 2021-08-16 22:57  wenxuehai  阅读(502)  评论(0编辑  收藏  举报
//右下角添加目录