由于我测试的环境是win10,挂载的目录发现有些限制(例如:测试发现挂载不到D盘)
1、【容器数据卷】
容器之间可以有一个数据共享的技术!Docker容器中产生的数据,同步到本地!
这就是卷技术!目录的挂载,将我们容器内的目录,挂载到Linux上面(或window上面)!
【docker run -it -v /c/Users/gaoqiang/docker.sync.folder/:/home centos /bin/bash】
在window中测试,只能挂载盘到用户的目录,例如:docker@default:/c/Users/gaopinqiang$ 测试如果
-v /d/test 只是挂载到docker主机里面的目录。window本机目录并不会创建这个文件。 这个时候我们在容器中的/home目录创建文件,window本机中的这个目录也会同步
可以通过 【docker inspect 容器id】 查看是否挂载成功。
"Mounts": [
{
"Type": "bind",
"Source": "/c/Users/gaopinqiang/docker.sync.folder",
"Destination": "/home",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
停止容器,在本机修改文件,启动容器后仍然是同步的。
[root@947bc6d88b40 home]# cat test.java
modify by window
[root@947bc6d88b40 home]#
好处:我们以后修改只需要在本地修改即可,容器内会自动同步!
2、【实战:安装MySQL】
【docker run -e MYSQL_ROOT_PASSWORD=123456 -v /c/Users/gwx284438/mysql/conf:/etc/mysql/conf.d -p 3307:3306 -d mysql:5.7】
发现将/var/lib/mysql挂载到我们本地会出现启动mysql失败问题。挂载到docker的目录不会。
【docker run -e MYSQL_ROOT_PASSWORD=123456 -v /c/Users/gwx284438/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -p 3307:3306 -d mysql:5.7】
这个时候mysql的数据会同步到docker的/home/mysql/data目录
备注:即使删除了mysql容器。后面再创建挂载相同的data目录的话,表数据还在。
3、【具名和匿名挂载】
匿名挂载:-v 容器内路径
docker run -d -P --name nginx01 -v /etc/nginx nginx
# 查看所有的volume的情况
➜ ~ docker volume ls
DRIVER VOLUME NAME
local 33ae588fae6d34f511a769948f0d3d123c9d45c442ac7728cb85599c2657e50d
local
# 这里发现,这种就是匿名挂载,我们在 -v只写了容器内的路径,没有写容器外的路径!
具名挂载:通过 -v 卷名:容器内路径
➜ ~ docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
➜ ~ docker volume ls
DRIVER VOLUME NAME
local juming-nginx
# 通过 -v 卷名:容器内路径
# 查看一下这个卷【docker volume inspect juming_nginx】
$ docker volume inspect juming_nginx
[
{
"CreatedAt": "2020-09-27T06:24:10Z",
"Driver": "local",
"Labels": null,
"Mountpoint": "/mnt/sda1/var/lib/docker/volumes/juming_nginx/_data",
"Name": "juming_nginx",
"Options": null,
"Scope": "local"
}
]
所有的docker容器内的卷,没有指定目录的情况下都是在/var/lib/docker/volumes/xxxx/_data下。
如果指定了目录,docker volume ls 是查看不到的(例如我们之前写的 -v /home/nginx:/etc/nginx nginx)
三种挂载: 匿名挂载、具名挂载、指定路径挂载
-v 容器内路径 #匿名挂载
-v 卷名:容器内路径 #具名挂载
-v /宿主机路径:容器内路径 #指定路径挂载 docker volume ls 是查看不到的,已斜杆开始
4、【数据卷容器】–volumes-from
一个容器直接使用另一个容器的数据卷,可以让多个MySQL同步数据!
例如:
启动第一个mysql容器,端口3307
【docker run -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -p 3307:3306 -d mysql:5.7】
加上--volumes-from参数启动第二个mysql ,端口3308
【docker run -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 -p 3308:3306 --volumes-from mysql01 -d mysql:5.7】
window上测试的时候能正常启动2个mysql,但是第二个mysql使用HeidiSQL工具连接不上问题。
结论:
容器之间的配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止。
但是一旦你持久化到了本地,这个时候,本地的数据是不会删除的!
5、【DockerFile介绍】
dockerfile是用来构建docker镜像的文件!命令参数脚本!
构建步骤:
1、 编写一个dockerfile文件
2、 docker build 构建称为一个镜像
3、 docker run运行镜像
4、 docker push发布镜像(DockerHub 、阿里云仓库)
DockerFile构建过程:
1、每个保留关键字(指令)都是必须是大写字母
2、执行从上到下顺序
3、#表示注释
4、每一个指令都会创建提交一个新的镜像曾,并提交!
【DockerFile的指令】
FROM # 基础镜像,一切从这里开始构建
MAINTAINER # 镜像是谁写的, 姓名+邮箱
RUN # 镜像构建的时候需要运行的命令
ADD # 步骤,tomcat镜像,这个tomcat压缩包!添加内容 添加同目录
WORKDIR # 镜像的工作目录
VOLUME # 挂载的目录
EXPOSE # 保留端口配置
CMD # 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代。
ENTRYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令
ONBUILD # 当构建一个被继承 DockerFile 这个时候就会运行ONBUILD的指令,触发指令。
COPY # 类似ADD,将我们文件拷贝到镜像中
ENV # 构建的时候设置环境变量!
【Dockerfile实战测试】创建自己的centos
# 1、编写Dockerfile文件
FROM centos
MAINTAINER gaoqiang<gaoqiang@huawei.com>
ENV MYPATH /usr/local
WORKDIR $MYPATH
EXPOSE 80
CMD echo $MYPATH
CMD echo "---end---"
CMD /bin/bash
# 2、通过这个文件构建镜像(特别注意后面有个.)
# 命令 docker build -f 文件路径 -t 镜像名:[tag] .
【docker build -f mydockerfile-centos -t qiang_centos:1.0 .】
成功会有下面的打印:
Successfully built c1cdfa249f94
Successfully tagged qiang_centos:1.0
# 3、测试运行。启动我们的centos,可以看到WORKDIR $MYPATH这个生效了。
$ docker run -it qiang_centos:1.0
[root@8c156c8536e5 local]# pwd
/usr/local
[root@8c156c8536e5 local]#
通过【docker history id】可以查看构建的历史
$ docker history qiang_centos:1.0
IMAGE CREATED CREATED BY SIZE COMMENT
c1cdfa249f94 6 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "/bin 0B
02641c0cd60b 6 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo 0B
13820e2c4c5f 6 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo 0B
ac4421f35831 6 minutes ago /bin/sh -c #(nop) EXPOSE 80 0B
7720b56e0b43 6 minutes ago /bin/sh -c #(nop) WORKDIR /usr/local 0B
12c15d13d87f 6 minutes ago /bin/sh -c #(nop) ENV MYPATH=/usr/local 0B
082e5849d94b 6 minutes ago /bin/sh -c #(nop) MAINTAINER gaoqiang<gaoqi 0B
0d120b6ccaa8 6 weeks ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 6 weeks ago /bin/sh -c #(nop) LABEL org.label-schema.sc 0B
<missing> 6 weeks ago /bin/sh -c #(nop) ADD file:538afc0c5c964ce0d 215MB
6、【Dockerfile中的CMD 和 ENTRYPOINT区别】
CMD # 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代。
ENTRYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令
测试CMD:
# 编写dockerfile文件
$ vim dockerfile-test-cmd
FROM centos
CMD ["ls","-a"]
# 构建镜像
$ docker build -f dockerfile-test-cmd -t cmd-test:0.1 .
# 运行镜像
$ docker run cmd-test:0.1
.
..
.dockerenv
bin
dev
# 想追加一个命令 -l 成为ls -al
$ docker run cmd-test:0.1 -l
docker: Error response from daemon: OCI runtime create failed: container_linux.go:349: starting container process caused "exec: \"-l\":
executable file not found in $PATH": unknown.
ERRO[0000] error waiting for container: context canceled
# cmd的情况下 -l 替换了CMD["ls","-l"]。 -l 不是命令所以报错了。
测试ENTRYPOINT:
# 编写dockerfile文件
$ vim dockerfile-test-entrypoint
FROM centos
ENTRYPOINT ["ls","-a"]
# 我们的命令,是直接拼接在我们得ENTRYPOINT命令后面的
$ docker run entrypoint-test:0.1 -l
total 56
drwxr-xr-x 1 root root 4096 May 16 06:32 .
drwxr-xr-x 1 root root 4096 May 16 06:32 ..
-rwxr-xr-x 1 root root 0 May 16 06:32 .dockerenv
lrwxrwxrwx 1 root root 7 May 11 2019 bin -> usr/bin
drwxr-xr-x 5 root root 340 May 16 06:32 dev
drwxr-xr-x 1 root root 4096 May 16 06:32 etc
drwxr-xr-x 2 root root 4096 May 11 2019 home
lrwxrwxrwx 1 root root 7 May 11 2019 lib -> usr/lib
lrwxrwxrwx 1 root root 9 May 11 2019 lib64 -> usr/lib64 ....
小结:比较清楚的原理图: