一、概述
本文旨在汇总整理Docker日常管理之知识碎片,以便日后回顾查看参考。
二、应用示例
2.1、Docker容器隔离之Namespace
Namespace:是容器虚拟化依赖的Linux 主要核心技术,用于各容器之间的隔离。主要通过以下六项隔离技术来实现:有两个伪文件系统:/proc和/sys/
● UTS: 允许每个container拥有独立的hostname(主机名)和domainname(域名),使其在网络上可以被视作一个独立的节点而非Host上的一个进程。
● IPC:contaner中进程交互还是采用linux常见的进程间交互方法,包括常见的信号量,消息队列和共享内存。container的进程间交互实际上还是host上具有相同pid中的进程交互。
● PID:不同用户的进程就是通过pid namesapce隔离开的,且不同namespace中可以有相同pid。所有的LXC(linux containers)进程在docker中的父进程为docker进程,每个LXC进程具有不同的namespace。
● NET:
● MNT:文件系统的挂载点。
● USRE:每个container可以有不同的user和groupid,也就是说可以在container内部用container内部的用户执行程序而非Host上的用户。
2.2、Docker之自由限制cgroup
eg1:docker run -it -m 200M --memory-swap 300M centos //-m或–memory:设置内存的使用限额,–memory-swap:设置swap(交换分区)的使用限额
eg2: docker run -it --name containerB -c 512 centos //containerB,cpu权重限制为512;-c或者–cpu-shares设置容器实验cpu的权重。如果不设置默认是1024
eg3: docker run -it --name testA --device-write-bps /dev/sda:30MB centos //容器testA限制该磁盘每秒写入的数量为为30MB;
其他参数:
-bps:每秒读写的数据量。byte per second
-iops:每秒io的次数。 io per second
--device-read-bps:设置读取设备的bps
--device-write-bps:设置写入设备的bps
--device-read-iops:设置读取设备的iops
--device-write-iops:设置写入设备的iops
2.3、给运行中的容器设置端口映射
有时我们想不停止容器的情况下,调整容器映射端口,那怎样在容器使用中,映射容器内应用的服务端口到本机宿主机器呢?
当容器中运行一些网络应用,要让外部访问这些应用时,可以通过 -P 或 -p 参数两种方式来指定端口映射。使用 -P(大) 参数时,Docker 会随机映射一个宿主本地端口到内部容器开放的网络端口上;使用 -p(小) 参数时,可以指定要映射的端口,并且在一个指定的端口上只可以绑定一个容器。支持的格式有:
IP:HostPort:ContainerPort
IP:ContainerPort
HostPort:ContainerPort
下面我们来分别举例说明:
eg1:docker run -d -P nginx //docker ps查看会发现,宿主机本地的随机分配了一个 3**** 端口被映射到了容器的 80 端口上,在本机浏览器访问 http://localhost:3**** 就会出现 nginx 欢迎页面
eg2:docker run -d -p 8080:80 nginx //使用 docker ps 可看到,本地主机的 8080 端口被映射到了容器的 80 端口
验证:命令格式:docker port CONTAINER [PRIVATE_PORT[/PROTO]]
使用 docker inspect + 容器ID 获取容器的具体信息:
eg3:给运行中的容器添加映射端口
docker inspect \`container_name` | grep IPAddress //将container_name 换成实际环境中的容器名,获得容器的IP地址
iptables -t nat -A DOCKER -p tcp --dport 8001 -j DNAT --to-destination 172.17.0.19:8000 //将容器的8000端口映射到docker主机的8001端口
或:
docker commit container_id foo/live //提交一个运行中的容器为镜像
docker run -d -p 8000:80 foo/live /bin/bash //运行镜像并添加端口映射,宿主8000到容器80,
2.4、修改运行中docker容器中的内容
docker中宿主机与容器(container)互相拷贝传递文件
docker cp mycontainer:/opt/testnew/file.txt /opt/test/ //从容器拷贝文件到宿主机
docker cp /opt/test/file.txt mycontainer:/opt/testnew/ //从宿主机拷贝文件到容器
sudo docker commit -m "描述内容" -a "author name" 32555789dd00 aipaper/devinz83:v2 //-m 来指定提交的说明信息,跟我们使用的版本控制工具一样;-a 可以指定更新的用户信息;之后是用来创建镜像的容器的 ID;最后指定目标镜像的仓库名和 tag 信息。创建成功后会返回这个镜像的 ID 信息
docker images //验证
REPOSITORY TAG
aipaper/devinz83 v2
#修改容器配置文件yaml
vi /opt/docker/yml/docker-compose-resty-redis.yml
docker stack deploy --compose-file=/opt/docker/yml/docker-compose-resty-redis.yml resty_redis //使用新修改后的镜像部署了docker应用
注:不管容器有没有启动,docker cp都会生效;完成后,使用 docker commit 命令来提交更新后的副本。
之后更新容器的yml文件,更新image为新的对象:
2.5、Docker容器迁移到其他服务器
有时我们会由于各种原因,比如硬件升级、数据中心变化,资源限制等因素,需要将当前docker容器所在迁移到其他资源池或主机。
1)导出和导入容器:
导出容器:即从容器的文件系统创建压缩文件,导出的文件保存为“gzip”文件;之后通过文件传输工具(如scp或rsync)将压缩文件复制到新服务器。再在新服务器中,将这个gzip文件导入到一个新容器中。
docker export container-name | gzip > container-name.gz
zcat container-name.gz | docker import - container-name
docker run -d container-name /bin/bash //使用“docker run”命令访问在新服务器中创建的新容器
注:导出容器工具的一个缺点是,它不导出容器的端口和变量,也不导出包含容器的底层数据。当尝试在另一台服务器中加载容器时,这可能会导致错误。对此,我们可另考虑使用Docker镜像迁移来将容器从一台服务器迁移到另一台服务器。
2)容器镜像迁移:
即我们迁移容器关联到的镜像到新的资源池,这也是将Docker容器迁移到另一台服务器的最常用方法。对于要迁移的容器,首先使用“Docker commit”命令将其Docker镜像保存到压缩文件中。
docker commit container-id image-name //生成的镜像将被压缩
之后将上述镜像上传到新服务器上,在新服务器中,将使用“docker run”创建一个新容器。
使用此方法,数据卷不会被迁移,但它会保留,在容器内创建的应用程序的数据。
3)先保存,再加载镜像
docker镜像是应用程序的代码、库、配置文件等的包。Docker容器是由这些镜像创建的。
可以使用“docker save”压缩镜像并将其迁移到新服务器。之后在新服务器中,使用“docker load”将压缩镜像文件用于创建新镜像。
docker save image-name > image-name.tar
cat image-name.tar | docker load
4)迁移数据卷:
Docker容器中的数据卷是共享目录,其中包含特定于容器的数据。卷中的数据是持久的,在容器重新创建期间不会丢失。
使用导出或提交工具将Docker容器或镜像从一台服务器迁移到另一台服务器时,不会迁移基础数据卷。在这种情况下,包含数据的目录将手动迁移到新服务器。然后在新服务器创建容器,引用该目录作为其数据卷。
另一个简单的方法是通过在“docker run”命令中传递“-volumes from”参数来备份和恢复数据卷。
docker run --rm --volumes-from datavolume-name -v $(pwd):/backup image-name tar cvf backup.tar /path-to-datavolume
docker run --rm --volumes-from datavolume-name -v $(pwd):/backup image-name bash -c "cd /path-to-datavolume && tar xvf /backup/backup.tar --strip 1"
上述命令中:datavolume-name是/path/to/volume,此命令提供数据卷的备份。要指定工作目录,还可以指定-w/backup。在/backup文件夹中生成的备份可以通过scp或ftp工具复制到新服务器。然后提取复制的备份并将其还原到新容器中的数据卷中。
5)迁移整个Docker容器:
以上方法仅适用于单个容器。但是将所有容器都要从一台服务器迁移到另一台服务器的情况下,我们采用另一种方法。此方法包括将整个docker目录(“/var/lib/docker”)复制到新服务器。为了使这种方法成功,需要确定几个关键点。
1、保留文件夹的权限和所有权。
2、迁移前停止Docker服务。
3、验证两台服务器中的Docker版本是否兼容。
4、迁移前后验证容器列表和功能。
5、环境变量和其他配置文件的路径。
6、如果此方法由于任何故障而无法工作,我们将配置自定义脚本以将容器和镜像从一台服务器迁移到另一台服务器。
2.6、查看docker镜像中文件
docker attach ContainerID //需要对应的container是运行中的,不处于stop状态
##对于未运行的,可以把Docker镜像中的文件复制到宿主来看,示例如下
sudo docker cp nginx-ubuntu-container:/etc/apt/sources.list ~/Documents/
2.7、运行容器:docker run常用选项
语法:docker run [option] 镜像名 [向启动容器中传入的命令]
常用可选参数说明:
-a stdin: 指定标准输入输出内容类型,可选 STDIN/STDOUT/STDERR 三项;
-i 表示以“交互模式”运行容器
-t 表示容器启动后会进入其命令行。加入这两个参数后,容器创建就能登录进去。即 分配一个伪终端。
--name 为创建的容器命名
-v 表示目录映射关系(前者是宿主机目录,后者是容器映射到宿主机上的目录,即宿主机目录:容器中目录),可以使用多个-v 做多个目录或文件映射,用来绑定一个卷。注意:最好做目录映射,在宿主机上做修改,然后共享到容器上。
-d 在run后面加上-d 参数,则会创建一个守护式容器在后台运行(这样创建容器后不 会自动登录容器,如果只加-i -t 两个参数,创建后就会自动进去容器)。
-p 表示端口映射,前者是宿主机端口,后者是容器内的映射端口。可以使用 多个-p 做多个端口映射,格式:主机(宿主)端口:容器端口
-P: 随机端口映射,容器内部端口随机映射到主机的端口
-e 为容器设置环境变量
-d, --detach=false 指定容器运行于前台还是后台,默认为false
-i, --interactive=false 打开STDIN,用于控制台交互
-t, --tty=false 分配tty设备,容器重新分配一个伪输入终端,通常与 -i 同时使用;该选项可以支持终端登录,默认为false
-u, --user="" 指定容器的用户
-a, --attach=[] 登录容器(必须是以docker run -d启动的容器)
-w, --workdir="" 指定容器的工作目录
-c, --cpu-shares=0 设置容器CPU权重,在CPU共享场景使用
-e, --env=[] 指定环境变量,容器中可以使用该环境变量
-m, --memory="" 指定容器的内存上限
-P, --publish-all=false 指定容器暴露的端口
-p, --publish=[] 指定容器暴露的端口
-h, --hostname="" 指定容器的主机名,-h "hostname": 指定容器的hostname
-v, --volume=[] 给容器挂载存储卷,挂载到容器的某个目录
--volumes-from=[] 给容器挂载其他容器上的卷,挂载到容器的某个目录
--cap-add=[] 添加权限,权限清单详见:http://linux.die.net/man/7/capabilities
--cap-drop=[] 删除权限,权限清单详见:http://linux.die.net/man/7/capabilities
--cidfile="" 运行容器后,在指定文件中写入容器PID值,一种典型的监控系统用法
--cpuset="" 设置容器可以使用哪些CPU,此参数可以用来容器独占CPU;--cpuset="0-2" or --cpuset="0,1,2": 绑定容器到指定CPU运行;
--device=[] 添加主机设备给容器,相当于设备直通
--dns=[] 指定容器的dns服务器,默认和宿主一致;
--dns-search=[] 指定容器的dns搜索域名,写入到容器的/etc/resolv.conf文件,默认和宿主一致
--entrypoint="" 覆盖image的入口点
--env-file=[] 从指定环境变量文件读入环境变量,文件格式为每行一个环境变量
--expose=[] 指定容器暴露的端口,即修改镜像的暴露端口
--link=[] 指定容器间的关联,使用其他容器的IP、env等信息,添加链接到另一个容器
--lxc-conf=[] 指定容器的配置文件,只有在指定--exec-driver=lxc时使用
--name="" 指定容器名字,后续可以通过名字进行容器管理,links特性需要使用名字
--network=host 表示将主机的网络环境映射到容器中,容器的网络与主机相同
--net="bridge" 指定容器网络设置:支持 bridge/host/none/container: 四种类型 bridge 使用docker daemon指定的网桥
host //容器使用主机的网络
container:NAME_or_ID >//使用其他容器的网路,共享IP和PORT等网络资源
none 容器使用自己的网络(类似--net=bridge),但是不进行配置
--privileged=false 指定容器是否为特权容器,特权容器拥有所有的capabilities
--restart="no" 指定容器停止后的重启策略:
no:容器退出时不重启
on-failure:容器故障退出(返回值非零)时重启
always:容器退出时总是重启
--rm=false 指定容器停止后自动删除容器(不支持以docker run -d启动的容器)
--sig-proxy=true 设置由代理接受并处理信号,但是SIGCHLD、SIGSTOP和SIGKILL不能被代理
【命令示例】:
docker run --name mynginx -d nginx:latest //创建并运行mynginx容器
docker run -P -d nginx:latest //以后台模式启动一个容器,并将容器的80端口映射到宿主机随机端口
docker run -p 80:80 -v /data:/data -d nginx:latest //将容器的 80 端口映射到主机的 80 端口,主机的目录 /data 映射到容器的 /data并挂载该卷
docker run -p 127.0.0.1:80:8080/tcp ubuntu bash //绑定容器的 8080 端口,并将其映射到本地主机 127.0.0.1 的 80 端口上
【容器的状态】:
created(已创建):创建容器但不会运行(None—create—created)
restarting(重启中):建议在运行容器时配置好重启策略。这是容器的一种自我修复能力,可以在指定事件或者错误后重启来完成自我修复。重启策略应用于每个容器,可以作为参数被强制传入 docker-container run 命令中,或者在 Compose 文件中声明;支持的重启策略包括 always、unless-stopped 和 on-failed。其中:–restart always 策略有一个很有意思的特性,当 daemon 重启的时候,停止的容器也会被重启。always 和 unless-stopped 的最大区别,就是那些指定了 --restart unless-stopped 并处于 Stopped (Exited) 状态的容器,不会在 Docker daemon 重启的时候被重启。on-failure 策略会在退出容器并且返回值不是 0 的时候,重启容器。就算容器处于 stopped 状态,在 Docker daemon 重启的时候,容器也会被重启。
/
running 或 Up(运行中):启动一个已经创建的容器后(created—start—running)
removing(迁移中)
paused(暂停)
exited(停止)
dead(死亡)
stoped(停止):停止/killed一个运行中的容器后;停止容器运行并不会损毁容器或者其中的数据
下图是容器的生命周期演进:
可知的是,容器的生命周期。可以根据需要多次停止、启动、暂停以及重启容器,并且这些操作执行得很快。但是容器及其数据是安全的。直至明确删除容器前,容器都不会丢弃其中的数据。就算容器被删除了,如果将容器数据存储在卷中,数据也会被保存下来。
$ docker container run -d --name always \
--restart always \
alpine sleep 1d
$ docker container run -d --name unless-stopped \
--restart unless-stopped \
alpine sleep 1d
$ docker container ls
CONTAINER ID IMAGE COMMAND STATUS NAMES
3142bd91ecc4 alpine "sleep 1d" Up 2 secs unless-stopped
4f1b431ac729 alpine "sleep 1d" Up 17 secs always
$ docker container stop always unless-stopped
$ docker container ls -a
CONTAINER ID IMAGE STATUS NAMES
3142bd91ecc4 alpine Exited (137) 3 seconds ago unless-stopped
4f1b431ac729 alpine Exited (137) 3 seconds ago always
$ systemlctl restart docker
$ docker container ls -a
CONTAINER CREATED STATUS NAMES
314..cc4 2 minutes ago Exited (137) 2 minutes ago unless-stopped
4f1..729 2 minutes ago Up 9 seconds always ##该容器重启了
2.8、容器其他命令
docker inspect mysql_cdh //通过容器名查看启动参数
docker inspect nginx2 | grep -i id //查看容器ID
docker inspect nginx2 | grep -i path //查看容器临时文件,每次创建时随机生成的文件(容器层)
docker logs 容器ID //查看容器内的标准输出
docker container rm 容器ID/name //结合-f 参数来一次性删除运行中的容器是可行的,不会发出任何告警;删除容器的最佳方式还是分两步,先停止容器然后删除。这样可以给容器中运行的应用/进程一个停止运行并清理残留数据的机会。
docker container stop 命令向容器内的 PID 1 进程发送了 SIGTERM 这样的信号。如果 10s 内进程没有终止,那么就会收到 SIGKILL 信号。
docker pause :暂停容器中所有的进程
docker unpause :恢复容器中所有的进程
docker history [OPTIONS] IMAGE // 查看指定镜像的创建历史;-H : 以可读的格式打印镜像大小和日期,默认为true;–no-trunc : 显示完整的提交记录;-q : 仅列出提交记录ID。
docker run是利用镜像生成容器,并启动容器,而docker start是启动一个之前生成过的容器;
docker top 容器ID //查看容器内运行的进程
docker exec和attach的区别:exec 是在容器中打开新的终端,并且可以启动新的进程,可以在容器外面直接运行命令,也可以进入容器里面运行命令;attach 直接进入容器启动命令的终端,不会启动新的进程。
2.9、Dockerfile文件
Dockerfile用于创建image镜像的文本类模板文件,文本内容包含了一条条构建镜像所需的指令和说明。出于管理和安全的考虑,docker官方建议所有的镜像文件应该由dockerfile来创建,而当前不少用户把docker当虚拟机来使用,甚至容器中安装SSH,从安全的角度,这是不恰当的。
FROM centos #定制的镜像都是基于 FROM 的镜像,这里的 centos就是定制需要的基础镜像。后续的操作都是基于 centos
RUN yum -y install wget #RUN:用于执行后面跟着的命令行命令,有2种模式:shell和cmd
,这里是shell模式,如果是cmd模式的话,格式参考:RUN ["可执行文件", "参数1", "参数2"];CMD 在docker run 时运行;RUN 是在 docker build。如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效。且CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖。
RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"
RUN tar -xvf redis.tar.gz
注:Dockerfile 的指令每执行一次都会在 docker 上新建一层。所以过多无意义的层,会造成镜像膨胀过大。如上例所示;执行后会创建 3 层镜像。可简化为以下格式:
FROM centos
RUN yum -y install wget \
&& wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \
&& tar -xvf redis.tar.gz #&& 符号连接命令,这样执行后,只会创建 1 层镜像
创建好dockerfile文件后,就可切到该文件目录下, 执行容器构建命令:
docker build -t nginx:v3 . #最后的 . 代表本次执行的上下文路径;
注:关于上下文路径,它是指 docker 在构建镜像,有时候想要使用到宿主本机的文件,docker build 命令得知这个路径后,会将路径下的所有内容打包。由于 docker 的运行模式是 C/S。我们本机是 C,docker 引擎是 S。实际的构建过程是在 docker 引擎下完成的,所以这个时候无法用到我们本机的文件。这就需要把我们本机的指定目录下的文件一起打包提供给 docker 引擎使用。如果未说明最后一个参数,那么默认上下文路径就是 Dockerfile 所在的位置。上下文路径下不要放无用的文件,因为一起打包发送给 docker 引擎太多的话,会造成构建过程缓慢。
2.10、Docker 文件存放路径查看及端口映射修改
1)启动一个容器:
docker run -d --name mysql_cdh \
-p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=123456 \
-v mysql-data:/var/lib/mysql \
--restart=always \
mysql:5.5 --character-set-server=utf8
2)查看容器的映射文件和启动参数:
docker inspect mysql_cdh /输出如下
[
{
"Id": "3aad772538b5e86705d3358362517a08d53f951aa6522e2881321135f05c8872",
"Created": "2019-09-25T01:43:37.720505875Z",
"Path": "docker-entrypoint.sh",
"Args": [
"--character-set-server=utf8"
],
...
"Name": "/mysql_cdh",
"HostConfig": {
"Binds": [
"mysql-data:/var/lib/mysql"
],
...
"NetworkMode": "default",
"PortBindings": {
"3306/tcp": [
{
"HostIp": "",
"HostPort": "3306"
}
]
},
"RestartPolicy": {
"Name": "always",
"MaximumRetryCount": 0
},
"Mounts": [
{
"Type": "volume",
"Name": "mysql-data",
"Source": "/var/lib/docker/volumes/mysql-data/_data",
"Destination": "/var/lib/mysql",
"Driver": "local",
"Mode": "z",
"RW": true,
"Propagation": ""
}
],
"Config": {
"Hostname": "3aad772538b5",
...
"ExposedPorts": {
"3306/tcp": {}
},
...
"Env": [
"MYSQL_ROOT_PASSWORD=123456",
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/mysql/bin:/usr/local/mysql/scripts",
"GOSU_VERSION=1.7",
"MYSQL_MAJOR=5.5",
"MYSQL_VERSION=5.5.62"
],
"Cmd": [
"--character-set-server=utf8"
],
3)查看容器的文件存放路径:
docker run -d --name nginx2 nginx #输出如下
a9c9f31cdccf13c3385f3de33443325d2e14d69458e6d679e54c8cf9e5ff24c8
docker inspect nginx2 | grep -i id #输出如下
"Id": "a9c9f31cdccf13c3385f3de33443325d2e14d69458e6d679e54c8cf9e5ff24c8",
"Pid": 2069,
"ExecIDs": null,
"ContainerIDFile": "",
docker inspect nginx2 | grep -i path #看容器临时文件--每次创建时随机生成的文件(容器层),输出如下
"Path": "nginx",
"ResolvConfPath": "/var/lib/docker/containers/a9c9f31cdccf13c3385f3de33443325d2e14d69458e6d679e54c8cf9e5ff24c8/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/a9c9f31cdccf13c3385f3de33443325d2e14d69458e6d679e54c8cf9e5ff24c8/hostname",
"HostsPath": "/var/lib/docker/containers/a9c9f31cdccf13c3385f3de33443325d2e14d69458e6d679e54c8cf9e5ff24c8/hosts",
"LogPath": "/var/lib/docker/containers/a9c9f31cdccf13c3385f3de33443325d2e14d69458e6d679e54c8cf9e5ff24c8/a9c9f31cdccf13c3385f3de33443325d2e14d69458e6d679e54c8cf9e5ff24c8-json.log",
4)修改容器端口(需先保存旧容器为镜像)
docker inspect mysql_port |egrep -i 'volum|Mount' -A 2 #输出如下
"Volumes": {
"/var/lib/mysql": {}
},
--
"Volumes": {
"/var/lib/mysql": {}
},
docker run --name t1 -d -e MYSQL_ROOT_PASSWORD=123456 -v mysql-test-dir:/var/lib/mysql/ -p 3308:3306 mysql:5.5 #输出如下
53f2a3c53d4c6769897ee484c3d2ff4e3f82ea1e390d4950b2162c08af05d7cc
docker ps #验证
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
53f2a3c53d4c mysql:5.5 "docker-entrypoint.s…" 3 seconds ago Up 3 seconds 0.0.0.0:3308->3306/tcp t1
docker commit -m mysql_test_chag-port_img t1 mysql_port #提交当前容器环境--保存为新的镜像
sha256:9f90be3c200c6a8b535478375c4caf86d589d231afae1293d28026f9248f8ae3
docker images #验证,查看镜像是否导出完成
REPOSITORY TAG IMAGE ID CREATED SIZE
mysql_port latest 9f90be3c200c 3 seconds ago 205MB
mysql 5.5 d404d78aa797 18 months ago 205MB
docker stop t1 #停止旧容器
docker run --name t2 -d -v mysql-test-dir:/var/lib/mysql/ -p 3309:3306 mysql_port #用上述镜像启动新容器
fd7cefe55db8bb2687ab044ff1473f0c935ac5ce867df81b3b13f570e9026868
# docker ps #验证
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fd7cefe55db8 mysql_port "docker-entrypoint.s…" 3 seconds ago Up 2 seconds 0.0.0.0:3309->3306/tcp t2
cd /var/lib/docker/containers/d93185e3a0....2e544ccfa #切入新容器,通过容器层文件,找到配置文件hostconfig.json,修改容器映射的端口
cat hostconfig.json
{"Binds":["/dockersuperset:/home/superset"],"ContainerIDFile":"",
"LogConfig":{"Type":"json-file","Config":{}},"NetworkMode":"default",
"PortBindings":{"8088/tcp":[{"HostIp":"","HostPort":"8099"}]}......
docker image inspect nginx |tail -n 22 #查看容器层文件存放位置
GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/bf20cf788cc053f00ff1467525d50e19bd1cf07a2167f72511bdfcb28918a472/diff:/var/lib/docker/overlay2/317d80bb7ae58ed288be9ebd84aeb5b4b3a1c06f3211f5d1f32d89b629d1876e/diff",
"MergedDir": "/var/lib/docker/overlay2/7782d0eb292fdc8bbd73bf9bae2d65468e8aba0bcd6baed55ac348618b80ae16/merged",
"UpperDir": "/var/lib/docker/overlay2/7782d0eb292fdc8bbd73bf9bae2d65468e8aba0bcd6baed55ac348618b80ae16/diff",
"WorkDir": "/var/lib/docker/overlay2/7782d0eb292fdc8bbd73bf9bae2d65468e8aba0bcd6baed55ac348618b80ae16/work"
},
"Name": "overlay2"
},
参考:
更多参考:https://www.jb51.net/article/207862.htm
2.11、修改容器挂载目录
这里介绍3种方法:修改配置文件,重新运行命令行指定和导入导出
#第一种、修改配置文件
systemctl stop docker.service //停止docker服务
vim /var/lib/docker/containers/container-ID/config.v2.json //修改配置文件中的目录位置,然后保存退出
"MountPoints":{"/home":{"Source":"/docker","Destination":"/home","RW":true,"Name":"","Driver":"","Type":"bind","Propagation":"rprivate","Spec":{"Type":"bind","Source":"//docker/","Target":"/home"}}}
systemctl start docker.service //启动docker服务
docker start <container-name/ID> //重新启动docker容器
#方法二:提交现有容器为新镜像,然后用新镜像启动容器
docker ps -a //输出如下
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5a3422adeead ubuntu:14.04 "/bin/bash" About a minute ago Exited (0) About a minute ago agitated_newton
docker commit 5a3422adeead newi_magename
docker run -ti -v "$PWD/dir1":/dir1 -v "$PWD/dir2":/dir2 new_imagename /bin/bash //-v指定修改的挂载目录
#方法三:将现有容器导出为新镜像,后续同步骤2
docker container export -o ./myimage.docker 容器ID
docker import ./myimage.docker newimagename
docker run -ti -v "$PWD/dir1":/dir1 -v "$PWD/dir2":/dir2 newimagename /bin/bash
2.12、Docker持久化存储原理
本节将介绍docker如何挂载宿主机磁盘目录,用以永久存储数据:
docker run -itd --volume /tmp/source:/tmp/destination --name test ubuntu/nginx bash //使用镜像ubuntu/nginx运行一个容器,挂载宿主本地目录/tmp/source到容器目录/tmp/destination,容器的名称为test, --volume (可以简写为-v);在宿主机目录 /tmp/source/下做的修改,可以同步到容器目录 /tmp/destination/ 中,反之一样。