Docker容器实践------docker中的镜像、容器与仓库
https://blog.csdn.net/xiaochenXIHUA/article/details/160119278
一、docker数据管理
默认容器的数据是保存在容器的可读写层,当容器被删除时其上的数据将会丢失,所以为了实现数据的持久性则需要选择一种数据持久技术来保存数据,当前有以下二种方式:
| 数据持久保存方法 | 说明 |
|---|---|
| 数据卷(Volumes) | 容器内的数据被存放到宿主机(linux)一个特定的目录下(/var/lib/docker/volumes/)。这个目录只有Docker可以管理,其他进程不能修改【若想持久保存容器的应用数据,Volumes是Docker推荐的挂载方式】。 |
| 挂载宿主机目录 (Bind mounts) | 容器内的数据被存放到宿主机文件系统的任意位置,甚至存放到一些重要的系统目录或文件中。除了Docker之外的进程也可以任意对他们进行修改。 |
1.1、数据卷(Volumes)
数据卷(volumes)完全由Docker进程创建和管理。可以通过命令【docker volume create】来创建一个指定的卷,也可以由Docker进程在创建容器或服务的过程中来创建。数据卷有如下三个特性:
| 数据卷的特性(Volumes) |
|---|
| 对数据卷的修改会立马生效 |
| 对数据卷的更新,不会影响镜像 |
| 数据卷默认会一直存在,即使容器被删除 |
除了使用【--mount】标记,还可以使用【-v】(即为--volume)参数,起初,-v用于独立容器,【--mount】用于swarm services。但是,从Docker 17.06开始,也可以使用【--mount】用于独立容器。--mount命令更精准详细,并且易理解。
【-v】或者【--volume】都是由3部分参数组成,使用":"间隔,且顺序不能颠倒。
| 【-v】用法 | 【--mount】用法 |
|---|---|
| 第一个部分是volumes名字,在宿主机上具有唯一性。若省略卷名,就是匿名卷,系统给出随机卷名。 | 由多个键值对组成,<key>=<value>。--mount要比-v或者--volume命令更长,但是更容易理解。常用的键值对有如下几个: |
| 第二部分是挂载到容器里的文件或文件夹路径。 | **【type】**可以是bind,volume或者tmpfs |
| 第三部分是选项列表分隔符,例如"or"。 | 【source】是数据卷(volumes)的名字,匿名volume可以省略。source可缩写为src |
| **【destination】**挂载到容器中的文件或目录路径。可也缩写为dst或者使用target。 | |
| **【readonly】**指定挂载在容器中为只读。 |
如果需要在删除容器的同时移除数据卷,可以在删除容器的时候使用【docker rm -v】这个命令。无主的数据卷可能会占据很多空间,要清理请使用【docker volume prune】命令。
bash
#手动创建数据卷并
#1-手动创建一个名为cktest的数据卷
docker volume create cktest
#2-查看当前所有的数据卷
docker volume ls
#3-查看指定数据卷的存储路径等信息(如:查看cktest数据卷)
docker volume inspect cktest
#创建名为web的容器,并将容器内的【/usr/share/nginx/html】目录内容映射到【cktest】数据卷上
#注意1:就算这个卷没有创建在生成容器的时候也会自动创建;在一次【docker run】中可以挂载多个数据卷
#注意2:容器内的目录映射到指定数据卷后,就算将容器删除了,数据卷的数据内容还是存在的
docker run -d -P \
--name web \
--mount source=cktest,target=/usr/share/nginx/html \
nginx:1.28.3


1.2、挂载主机目录(Bind mounts)
在docker的早期版本中就存在的功能,与volumes相比,它的功能比较局限。当使用【bind mounts】时,宿主机的目录或文件被挂载到容器中。容器将按照挂载目录或文件的绝对路径来使用或修改宿主机的中的数据。宿主机中的目录或文件不需要预先存在。
但是,挂载主机目录【Bind mounts】方式无法通过Docker CLI来管理;另外,使用bind mounts的容器可以在容器内部的进程对主机文件系统进行修改,包括创建,修改和删除重要的系统文件和目录,这个功能虽然很强大,但显然也会造成安全方面的影响。所以还是推荐数据卷(Volumes)管理方式。
bash
#挂载主机目录作为数据卷命令示例
docker run -d -P \
--name web1 \
--mount type=bind,source=/data/docker/cktest,target=/usr/share/nginx/html \
nginx:1.28.3
如上"挂载主机目录作为数据卷命令示例"是加载宿主机的【/data/docker/cktest】目录到容器的【/usr/share/nginx/html】目录。本地目录的路径必须是绝对路径,以前使用 -v 参数时如果本地目录不存在 Docker 会自动为你创建一个文件夹,现在使用 --mount 参数时如果本地目录不存在,Docker 会报错。
上面命令执行后,你会发现,docker容器虽然启动了,但挂载的主机目录【/data/docker/cktest】还是空的,这是因为此种模式下【【/data/docker/cktest】】目录的内容会覆盖容器内的【/usr/share/nginx/html】目录,由于【/data/docker/cktest】目录是空的,因此容器内的【/usr/share/nginx/html】目录也变成空的了!


bash
#Docker挂载宿主机目录的默认权限是读写,用户也可以通过增加readonly指定为只读
docker run -d -P \
--name web1 \
--mount type=bind,source=/data/docker/cktest,target=/usr/share/nginx/html,readonly \
nginx:1.28.3
#如上命令这样加了readonly之后,【/data/docker/cktest】就挂载为只读了。若你在容器内【/usr/share/nginx/html】目录新建文件,会显示"Read-only file system"错误。
#除了可以挂载一个宿主机目录,还是可以挂载宿主机的某个文件【这样就可以记录在容器输入过的命令】
docker run --rm -it \
--mount type=bind,source=$HOME/.bash_history,target=/root/.bash_history \
centos:7.9.2009 \
bash
1.3、数据卷与挂载主机目录的数据覆盖规则
【数据卷】的使用场景:希望将容器中的文件内容都放到主机上时(注意:主机的数据卷必须是空目录;如:mysql数据)。
【挂载主机目录】的使用场景:希望将主机上已存在的文件内容放到容器中去运行(如:主机上写好的配置文件)。
| docker数据管理方式 | 数据覆盖规则 |
|---|---|
| 数据卷 | 《1》若挂载一个空的数据卷到容器中的一个非空目录中,则容器非空目录下的文件会被复制到该空数据卷中。 《2》若挂载一个非空数据卷到容器的一个目录中,则容器目录中原来的数据会被全部清空(覆盖),且容器的目录中会直接显示数据卷中的所有数据。 |
| 挂载主机目录 | 主机的目录始终覆盖掉容器内的目录。 |
二、Docker的网络与容器互联
2.1、外部访问容器
Docker允许通过外部访问容器或容器互联的方式来提供网络服务。
容器中可以运行一些网络应用,要让外部也可以访问这些应用,可以通过大写【-P】或小写【-p】参数来指定端口映射(本质是docker调用iptables来实现端口映射)。当使用大写【-P】标记时,Docker会随机映射一个大于3W的端口到内部容器开放的网络端口。
bash
#启动一个nginx容器(通过随机映射端口到内部容器端口)
docker run -d -P \
--name web \
--mount source=cktest,target=/usr/share/nginx/html \
--restart=always \
nginx:1.28.3
#通过使用【docker ps】命令可以看到,本地宿主机的32771端口被映射到了容器的80端口,此时通过访问本机的32771端口即可访问容器内web应用提供的界面。


| 另一个参数"-p"则可以指定要映射的端口,并且,在一个指定端口上只可以绑定一个容器。支持的格式有: |
|---|
| 《1》ip:hostPort:containerPort 《2》ip::containerPort 《3》hostPort:containerPort |
bash
#启动一个nginx容器(通过【hostPort:containerPort】格式将宿主机的8091端口映射到容器的80端口
#此时默认会绑定宿主机本地所有网络接口上的所有地址)
docker run -d -p 8091:80 \
--name web1 \
--mount source=cktest,target=/usr/share/nginx/html \
--restart=always \
nginx:1.28.3
#启动一个nginx容器(通过【ip:hostPort:containerPort】格式将宿主机指定地址的8092端口映射到容器的80端口
#此时默认会绑定宿主机本地的127.0.0.1网络接口)
docker run -d -p 127.0.0.1:8092:80 \
--name web2 \
--mount source=cktest,target=/usr/share/nginx/html \
--restart=always \
nginx:1.28.3
#启动一个nginx容器(通过【ip::containerPort】格式将宿主机指定地址的任意端口映射到容器的80端口
#此时默认会绑定宿主机本地的localhost的网络接口)
docker run -d -p 127.0.0.1::80 \
--name web3 \
--mount source=cktest,target=/usr/share/nginx/html \
--restart=always \
nginx:1.28.3


bash
#还可直接查看指定容器名称或容器ID的端口映射配置语法
docker port 容器名称或容器ID
#通过小写【-p】参数还可以多次使用来绑定多个端口
docker run -d -p 6000:5000 -p 3000:80 training/webapp python app.py
2.2、容器互联
若你之前有Docker使用经验,那么你对【--link】参数应该比较熟悉,它就是用来进行容器互联的。但是,随着Docker网络的完善和版本的升级,强烈建议大家将容器加入自定义的Docker网络来连接多个容器,而不是使用"--link"参数。
注意:若你有多个容器之间需要互相连接,推荐使用Docker Compose。
bash
#容器互联
#1-首先,新建docker网络(【-d】参数指定Docker网络类型,有bridge、overlay等)
docker network create -d bridge mynet
#2-接着,新运行两个容器,先运行第一个容器并连接到新建的mynet网络
docker run -it --rm --name busybox1 --network mynet busybox sh
#3-然后,打开一个新的终端,再运行一个容器并加入到mynet网络
docker run -it --rm --name busybox2 --network mynet busybox sh
#4-继续打开第三个终端,查看容器信息
docker ps
#5-最后,在第一个容器【busybox1】中ping第二个容器【busybox2】看是否能通,并反之测试,若可以通,则表示两个容器的网络互通
ping busybox2
ping busybox1




三、其他资料
Linux的软件防火墙iptables
https://blog.csdn.net/xiaochenxihua/article/details/150069372