https://www.docker.com/
https://hub.docker.com/
可以在上面发布自己的镜像,也可以拉取别人发布的镜像
虚拟化技术特点:1.资源占用多 2.冗余步骤多 3.启动很慢
容器化技术:容器化技术不是模拟的一个完整的操作系统
比较Docker和虚拟机的不同:
1.传统虚拟机,虚拟出硬件,运行一个完整的操作系统,然后在这个系统上安装和运行软件。
2.Docker容器内的应用直接运行在宿主机的内核中,容器是没有自己的内核的,也没有虚拟硬件。
3.每个容器都是相互隔离的,每个容器都有属于自己的文件系统,互不影响。
容器化带来的好处
相关名词
(安装docker的过程在这里—>http://hyxjackson.gitee.io/myblog/2022/04/22/Java%E9%83%A8%E5%88%86%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE/#more)
# 1. 卸载依赖
yum remove docker-ce docker-ce-cli containerd.io
# 2. 删除资源 . /var/lib/docker是docker的默认工作路径
rm -rf /var/lib/docker
docker是怎么工作的?
Docker是一个Client-Server结构的系统,Docker的守护进程运行在主机上,通过Socket从客户端访问!Docker Server接收到Docker-Client的指令,就会执行这个指令!
Docker为什么比(虚拟机)VM Ware快?
1、Docker比虚拟机更少的抽象层
2、Docker利用宿主机的内核,VM需要的是Guest OS
Docker新建一个容器的时候,不需要像虚拟机一样重新加载一个操作系统内核,直接利用宿主机的操作系统,而虚拟机是需要加载Guest OS。
Docker和VM的对比如下:
docker version #查看docker的版本信息
docker info #查看docker的系统信息,包括镜像和容器的数量
docker 命令 --help #帮助命令(可查看可选的参数) (查看某个具体命令的用法)
命令的帮助文档地址:https://docs.docker.com/engine/reference/commandline/docker/
1.docker images 查看本地主机的所有镜像
[root@iZwz99sm8v95sckz8bd2c4Z ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest bf756fb1ae65 11 months ago 13.3kB
#解释:
1.REPOSITORY 镜像的仓库源
2.TAG 镜像的标签
3.IMAGE ID 镜像的id
4.CREATED 镜像的创建时间
5.SIZE 镜像的大小
# 可选参数
-a/--all 列出所有镜像
-q/--quiet 只显示镜像的id
2.docker search 搜索镜像
[root@iZwz99sm8v95sckz8bd2c4Z ~]# docker search mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 10308 [OK]
mariadb MariaDB is a community-developed fork of MyS… 3819 [OK]
mysql/mysql-server Optimized MySQL Server Docker images. Create… 754 [OK]
percona Percona Server is a fork of the MySQL relati… 517 [OK]
centos/mysql-57-centos7 MySQL 5.7 SQL database server 86
mysql/mysql-cluster Experimental MySQL Cluster Docker images. Cr… 79
centurylink/mysql Image containing mysql. Optimized to be link… 60 [OK]
#可选参数
Search the Docker Hub for images
Options:
-f, --filter filter Filter output based on conditions provided
--format string Pretty-print search using a Go template
--limit int Max number of search results (default 25)
--no-trunc Don't truncate output
#搜索收藏数大于3000的镜像
[root@iZwz99sm8v95sckz8bd2c4Z ~]# docker search mysql --filter=STARS=3000
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 10308 [OK]
mariadb MariaDB is a community-developed fordockerk of MyS… 3819 [OK]
123456789101112131415161718192021222324252627
3.docker pull 镜像名[:tag] 下载镜像 ,tag就是版本号
[root@iZwz99sm8v95sckz8bd2c4Z ~]# docker pull mysql
Using default tag: latest #如果不写tag,默认版本就是latest(最新版)
latest: Pulling from library/mysql
6ec7b7d162b2: Pull complete #分层下载,docker image的核心-联合文件系统
fedd960d3481: Pull complete
7ab947313861: Pull complete
64f92f19e638: Pull complete
3e80b17bff96: Pull complete
014e976799f9: Pull complete
59ae84fee1b3: Pull complete
ffe10de703ea: Pull complete
657af6d90c83: Pull complete
98bfb480322c: Pull complete
6aa3859c4789: Pull complete
1ed875d851ef: Pull complete
Digest: sha256:78800e6d3f1b230e35275145e657b82c3fb02a27b2d8e76aac2f5e90c1c30873 #签名
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest #下载来源的真实地址 #docker pull mysql等价于docker pull
docker.io/library/mysql:latest
123456789101112131415161718
指定版本下载
[root@iZwz99sm8v95sckz8bd2c4Z ~]# docker pull mysql:5.7 (得看docker仓库(docker hub)有什么版本)
5.7: Pulling from library/mysql
6ec7b7d162b2: Already exists
fedd960d3481: Already exists
7ab947313861: Already exists
64f92f19e638: Already exists
3e80b17bff96: Already exists
014e976799f9: Already exists
59ae84fee1b3: Already exists
7d1da2a18e2e: Pull complete
301a28b700b9: Pull complete
529dc8dbeaf3: Pull complete
bc9d021dc13f: Pull complete
Digest: sha256:c3a567d3e3ad8b05dfce401ed08f0f6bf3f3b64cc17694979d5f2e5d78e10173
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7
4.docker rmi 删除镜像
rmi是remove image的缩写
#1.删除指定的镜像id
[root@iZwz99sm8v95sckz8bd2c4Z ~]# docker rmi -f 镜像id
#2.删除多个镜像id
[root@iZwz99sm8v95sckz8bd2c4Z ~]# docker rmi -f 镜像id 镜像id 镜像id
#3.删除全部的镜像id
[root@iZwz99sm8v95sckz8bd2c4Z ~]# docker rmi -f $(docker images -aq)
如拉取一个centos镜像
docker pull centos
运行容器的命令说明:
docker run [可选参数] image
#参数说明
--name="名字" 指定容器名字
-d 后台方式运行
-it 使用交互方式运行,进入容器查看内容(是-i和-t两个命令合在一起的)
-p 指定容器的端口(小写的p)
(
-p ip:主机端口:容器端口 配置主机端口映射到容器端口
-p 主机端口:容器端口
-p 容器端口
)
-P 随机指定端口(大写的P)
运行并进入容器centos
[root@iZwz99sm8v95sckz8bd2c4Z ~]# docker run -it centos /bin/bash
[root@bd1b8900c547 /]# ls #(bd1b8900c547是容器id)
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
退出容器命令:
#exit 停止并退出容器(后台方式运行则仅退出)
#Ctrl+P+Q 不停止容器退出
[root@bd1b8900c547 /]# exit
exit
[root@iZwz99sm8v95sckz8bd2c4Z ~]#
列出运行过的容器命令:
#docker ps
# 列出当前正在运行的容器
-a # 列出所有容器的运行记录
-n=? # 显示最近创建的n个容器
-q # 只显示容器的编号
[root@iZwz99sm8v95sckz8bd2c4Z ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@iZwz99sm8v95sckz8bd2c4Z ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bca129320bb5 centos "/bin/bash" 4 minutes ago Exited (0) 3 minutes ago optimistic_shtern
bd1b8900c547 centos "/bin/bash" 6 minutes ago Exited (0) 5 minutes ago cool_tesla
cf6adbf1b506 bf756fb1ae65 "/hello" 5 hours ago Exited (0) 5 hours ago optimistic_darwin
删除容器命令:
docker rm 容器id #删除指定的容器,不能删除正在运行的容器,强制删除使用 rm -f
docker rm -f $(docker ps -aq) #删除所有的容器
docker ps -a -q|xargs docker rm #删除所有的容器
启动和停止容器命令:
docker start 容器id #启动容器
docker restart 容器id #重启容器
docker stop 容器id #停止当前运行的容器
docker kill 容器id #强制停止当前容器
[root@iZwz99sm8v95sckz8bd2c4Z ~]# docker logs --help
Usage: docker logs [OPTIONS] CONTAINER
Fetch the logs of a container
Options:
--details Show extra details provided to logs
-f, --follow Follow log output
--since string Show logs since timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes)
-n, --tail string Number of lines to show from the end of the logs (default "all")
-t, --timestamps Show timestamps
--until string Show logs before a timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes)
常用:
docker logs -tf 容器id
docker logs --tail number 容器id #num为要显示的日志条数
#docker容器后台运行,必须要有一个前台的进程,否则会自动停止
#编写shell脚本循环执行,使得centos容器保持运行状态
[root@iZwz99sm8v95sckz8bd2c4Z ~]# docker run -d centos /bin/sh -c "while true;do echo hi;sleep 5;done"
c703b5b1911ff84d584390263a35707b6024816e1f46542b61918a6327a570dc
[root@iZwz99sm8v95sckz8bd2c4Z ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c703b5b1911f centos "/bin/sh -c 'while t…" 13 seconds ago Up 10 seconds pedantic_banach
[root@iZwz99sm8v95sckz8bd2c4Z ~]# docker logs -tf --tail 10 c703b5b1911f #10表示显示10条日志
2020-12-27T03:34:07.255599560Z hi
2020-12-27T03:34:12.257641517Z hi
2020-12-27T03:34:17.259706294Z hi
2020-12-27T03:34:22.261693707Z hi
2020-12-27T03:34:27.262609289Z hi
2020-12-27T03:34:32.267862677Z hi
2020-12-27T03:34:37.270382873Z hi
2020-12-27T03:34:42.272414182Z hi
2020-12-27T03:34:47.274823243Z hi
2020-12-27T03:34:52.277419274Z hi
# docker top 容器id
[root@iZwz99sm8v95sckz8bd2c4Z ~]# docker top c703b5b1911f
UID PID PPID C STIME TTY TIME CMD
root 11156 11135 0 11:31 ? 00:00:00 /bin/sh -c while true;do echo hi;sleep 5;done
root 11886 11156 0 11:43 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 5
[root@iZwz99sm8v95sckz8bd2c4Z ~]# docker inspect 容器id
因为通常我们的容器都是使用后台方式来运行的,有时需要进入容器修改配置
方式一:(比较常用)
[root@iZwz99sm8v95sckz8bd2c4Z ~]# docker exec -it 容器id /bin/bash
[root@c703b5b1911f /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
[root@c703b5b1911f /]# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 03:31 ? 00:00:00 /bin/sh -c while true;do echo hi;sleep 5;done
root 279 0 0 03:54 pts/0 00:00:00 /bin/bash
root 315 1 0 03:56 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 5
root 316 279 0 03:56 pts/0 00:00:00 ps -ef
方式二:
[root@iZwz99sm8v95sckz8bd2c4Z ~]# docker attach 容器id
docker exec 进入容器后开启一个新的终端,可以在里面操作
docker attach 进入容器正在执行的终端,不会启动新的进程
拷贝操作的命令如下:
#拷贝容器的文件到主机中
docker cp 容器id:容器内路径 目的主机路径
#拷贝宿主机的文件到容器中
docker cp 目的主机路径 容器id:容器内路径
#进入容器
[root@iZwz99sm8v95sckz8bd2c4Z ~]# docker exec -it 容器id /bin/bash
[root@c703b5b1911f /]# cd home
[root@c703b5b1911f home]# ls
#touch 新建文件
[root@c703b5b1911f home]# touch test.java
[root@c703b5b1911f home]# ls
test.java
[root@c703b5b1911f home]# exit
exit
[root@iZwz99sm8v95sckz8bd2c4Z ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c703b5b1911f centos "/bin/sh -c 'while t…" 35 minutes ago Up 35 minutes pedantic_banach
[root@iZwz99sm8v95sckz8bd2c4Z ~]# docker cp 容器id:/home/test.java /home
[root@iZwz99sm8v95sckz8bd2c4Z ~]# ls /home
hai pan test.java
命令小节的图解如下:
小拓展:容器的启动
1.前台交互式启动docker容器:docker run -it image:tag /bin/bash
2.后台守护式启动docker容器:docker run -d image:tag /bin/bash
3.前台交互式启动与后台守护式启动适应场景:
前台交互式启动适合ubuntu,nginx 。,因为ubuntu,nginx没有前台进程,如果使用后台守护式启动会导致容器立即自杀,它觉得没事可做了。这是docker机制的问题,所以最佳解决方案是以前台交互式启动,表示我还要交互操作。
后台守护式启动适合redis这些有前台进程的镜像,因为容器不会自动挂掉,并且若redis使用前台交互式启动,被操作人员不小心关掉终端(如exit,ctrl+c),会导致穿透、雪崩等一系列问题。所以redis适合后台守护式启动。
docker机制:docker容器后台运行,就必须有一个前台进程
工作中我们一般使用 docker run -d image:tag /bin/bash启动容器,再通过docker exec -it 容器ID /bin/bash,最为安全可靠。
docker pull nginx #拉取镜像
# -d 后台启动
# --name 名字 表示给容器起名
# -p 宿主机端口:容器端口
docker run -d --name nginx01 -p 3344:80 nginx #后台启动 3344是服务器对外端口,80是docker内部端口,通过服务器的3344端口就可以访问docker的80端口 (个人认为这里是docker做了映射)
curl localhost:3344 #查看本机3344
docker exex -it nginx01 /bin/bash #进入容器
ip:3344 #公网访问,(这里ip要填你的服务器的ip)
#可以看到结果访问到的就是nginx的默认首页
docker stop 容器id #停止容器
# 官方使用
docker run -it --rm tomcat:9.0
# 我们之前启动都是后台启动,退出容器之后,容器嗨是可以查到,而docker run -it --rm tomcat:9.0一般用来测试,用完即删(前期学习不建议这么用)
docker pull tomca:9.0 #拉取镜像
docker run -d -p 3355:8080 --name tomcat01 tomcat #启动
#通过外部ip访问,如果报404,说明官网的这个tomcat镜像是阉割版的tomcat,并不是完全版的
docker exec -it tomcat01 /bin/bash
#发现问题
# 1、Linux命令少了
# 2、tomcat中没有webapps
#阿里云镜像的原因。默认是最小的镜像,所有不必要的都删掉,保证最小的可运行的环境
#发现webapps.dist目录
# 可以把webapps.dist目录下的文件拷贝到webapps下,然后再重新访问
cp -r webapps.dist webapps
ES就是 ElasticSearch。没学过的小伙伴可以自行查阅一下
问题
# 1、es暴露的端口很多
# 2、es十分消耗内存
# 3、es的数据一般需要放置到安全目录! 挂载
# --net somenetwork 网络配置
docker run -d --name elasticsearch --net somenetwork -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:tag #(tag换成版本号)
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2
# docker十分耗内存,启动会卡
docker stats (容器id) #查看cpu的状态 (可以加上容器id)
curl localhost:9200 #本地测试
# 启动的时候修改配置 -e ES_JAVA_OPTS="-Xms64m -Xmx512m" 配置ElasticSearch的虚拟机占用的内存大小
docker run -d --name elasticsearch02 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.6.2
思考:kibana如何才能连接es?如何通过网络才能连接过去
管理镜像的工具
docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
访问测试 : 服务器ip:8088
这里第一次进来需要设置密码: 我这里是admin123+
选择local连接即可
镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需要的所有内容,包括代码,运行时(一个程序在运行或者在被执行的依赖)、库,环境变量和配置文件。
Docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统是UnionFS联合文件系统。
[root@iZwz9b8v7o84uw1vut700pZ ~]# docker image inspect nginx:latest
[
{
"Id": "sha256:605c77e624ddb75e6110f997c58876baa13f8754486b461117934b24a9dc3a85",
"RepoTags": [
"nginx:latest"
],
"RepoDigests": [
"nginx@sha256:0d17b565c37bcbd895e9d92315a05c1c3c9a29f762b011a10c54a66cd53c9b31"
],
"Parent": "",
"Comment": "",
"Created": "2021-12-29T19:28:29.892199479Z",
"Container": "ca3e48389f7160bc9d9a892d316fcbba459344ee3679998739b1c3cd8e56f7da",
"ContainerConfig": {
"Hostname": "ca3e48389f71",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"ExposedPorts": {
"80/tcp": {}
},
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"NGINX_VERSION=1.21.5",
"NJS_VERSION=0.7.1",
"PKG_RELEASE=1~bullseye"
],
"Cmd": [
"/bin/sh",
"-c",
"#(nop) ",
"CMD [\"nginx\" \"-g\" \"daemon off;\"]"
],
"Image": "sha256:82941edee2f4d17c55563bb926387c3ae39fa1a99777f088bc9d3db885192209",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": [
"/docker-entrypoint.sh"
],
"OnBuild": null,
"Labels": {
"maintainer": "NGINX Docker Maintainers "
},
"StopSignal": "SIGQUIT"
},
"DockerVersion": "20.10.7",
"Author": "",
"Config": {
"Hostname": "",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"ExposedPorts": {
"80/tcp": {}
},
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"NGINX_VERSION=1.21.5",
"NJS_VERSION=0.7.1",
"PKG_RELEASE=1~bullseye"
],
"Cmd": [
"nginx",
"-g",
"daemon off;"
],
"Image": "sha256:82941edee2f4d17c55563bb926387c3ae39fa1a99777f088bc9d3db885192209",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": [
"/docker-entrypoint.sh"
],
"OnBuild": null,
"Labels": {
"maintainer": "NGINX Docker Maintainers "
},
"StopSignal": "SIGQUIT"
},
"Architecture": "amd64",
"Os": "linux",
"Size": 141479488,
"VirtualSize": 141479488,
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/4c79c395f5276d6c16a5bb333597bd738c7fa91b2416db4e794feef3da840fd7/diff:/var/lib/docker/overlay2/d470f08d952b1012089ae05d2805014103385170fdfa4ae501190faef6abf68e/diff:/var/lib/docker/overlay2/aaed06144bf25b92f0a78704427cf79b9a9b4b7f4812173b3443d2d09ce59b09/diff:/var/lib/docker/overlay2/8f7e3a46f2c363ebb060a3695efc59fbec3202b01a9a6f17af4b607a93e84133/diff:/var/lib/docker/overlay2/8693e5bafb4e5803078339692b1733d67ce51cfdd37109e0a8cbec45103827cc/diff",
"MergedDir": "/var/lib/docker/overlay2/3781000955df3873afe2989265b4576804fc9cf710696d18db89c11a502e2446/merged",
"UpperDir": "/var/lib/docker/overlay2/3781000955df3873afe2989265b4576804fc9cf710696d18db89c11a502e2446/diff",
"WorkDir": "/var/lib/docker/overlay2/3781000955df3873afe2989265b4576804fc9cf710696d18db89c11a502e2446/work"
},
"Name": "overlay2"
},
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:2edcec3590a4ec7f40cf0743c15d78fb39d8326bc029073b41ef9727da6c851f",
"sha256:e379e8aedd4d72bb4c529a4ca07a4e4d230b5a1d3f7a61bc80179e8f02421ad8",
"sha256:b8d6e692a25e11b0d32c5c3dd544b71b1085ddc1fddad08e68cbd7fda7f70221",
"sha256:f1db227348d0a5e0b99b15a096d930d1a69db7474a1847acbc31f05e4ef8df8c",
"sha256:32ce5f6a5106cc637d09a98289782edf47c32cb082dc475dd47cbf19a4f866da",
"sha256:d874fd2bc83bb3322b566df739681fbd2248c58d3369cb25908d68e7ed6040a6"
]
},
"Metadata": {
"LastTagTime": "0001-01-01T00:00:00Z"
}
}
]
这里指示了分层信息:
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:2edcec3590a4ec7f40cf0743c15d78fb39d8326bc029073b41ef9727da6c851f",
"sha256:e379e8aedd4d72bb4c529a4ca07a4e4d230b5a1d3f7a61bc80179e8f02421ad8",
"sha256:b8d6e692a25e11b0d32c5c3dd544b71b1085ddc1fddad08e68cbd7fda7f70221",
"sha256:f1db227348d0a5e0b99b15a096d930d1a69db7474a1847acbc31f05e4ef8df8c",
"sha256:32ce5f6a5106cc637d09a98289782edf47c32cb082dc475dd47cbf19a4f866da",
"sha256:d874fd2bc83bb3322b566df739681fbd2248c58d3369cb25908d68e7ed6040a6"
]
},
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mzqNLUsd-1651031629498)(https://gitee.com/hyxJackson/picturesave/raw/master/20210718123636415.png)]
使用docker commit 命令提交容器成为一个新的版本
docker commit -m=“提交的描述信息” -a="作者" 容器id 目标镜像名:[TAG]
123
由于默认的Tomcat镜像的webapps文件夹中没有任何内容,需要从webapps.dist中拷贝文件到webapps文件夹。下面自行制作镜像:就是从webapps.dist中拷贝文件到webapps文件夹下,并提交该镜像作为一个新的镜像。使得该镜像默认的webapps文件夹下就有文件。具体命令如下:
# 启动默认tomcat,发现webapps目录下没有东西
[root@iZwz9b8v7o84uw1vut700pZ ~]# docker run -it --rm tomcat:9.0
[root@iZwz9b8v7o84uw1vut700pZ ~]# docker exec -it 34a4760d9b87 /bin/bash
root@34a4760d9b87:/usr/local/tomcat# cp -r webapps.dist/* webapps
root@34a4760d9b87:/usr/local/tomcat# cd webapps
root@34a4760d9b87:/usr/local/tomcat/webapps# ls
ROOT docs examples host-manager manager
ip:8080访问,可以看到tomcat的默认首页
如果无法访问,记得查看Linux防火墙的8080端口以及阿里云的安全组有没有开放8080端口
# 提交自己的镜像 docker commit -m="add webapps" -a="Kay" 34a4760d9b87 mytomcat:1.0
[root@iZwz9b8v7o84uw1vut700pZ ~]# docker commit -m="add webapps" -a="Kay" 34a4760d9b87 mytomcat:1.0
sha256:17cb58cc1f500837eb2bb56ba1802cf2011d7a53b1e9d3f92928b5d7458c1e97
# 可以看到我们自己的镜像 mytomcat 已经提交好了,版本号也是我们自己设定的版本号 1.0
[root@iZwz9b8v7o84uw1vut700pZ ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mytomcat 1.0 17cb58cc1f50 8 seconds ago 685MB
rabbitmq management 32d80c948e6c 11 days ago 257MB
mongo latest b21ad2afe409 13 days ago 700MB
nginx latest 605c77e624dd 3 months ago 141MB
tomcat 9.0 b8e65a4d736d 4 months ago 680MB
hello-world latest feb5d9fea6a5 7 months ago 13.3kB
centos latest 5d0da3dc9764 7 months ago 231MB
portainer/portainer latest 580c0e4e98b0 13 months ago 79.1MB
一个小技巧
如果想要保存当前容器的状态,就可以通过commit来提交,获得一个镜像
就好比虚拟机中的快照,可以保存当前的状态
Docker将运用与运行的环境打包形成容器运行, Docker容器产生的数据,如果不通过docker commit生成新的镜像,使得数据做为镜像的一部分保存下来, 那么当容器删除后,数据自然也就没有了。 为了能保存数据在Docker中我们使用卷技术。
容器之间可以有一个数据共享的技术(卷技术)!Docker容器中产生的数据,同步到本地。
卷技术可以将我们容器内的目录,挂载到Linux主机上
卷就是目录或文件,存在于一个或多个容器中,由Docker挂载到容器,但卷不属于联合文件系统(Union FileSystem),因此能够绕过联合文件系统提供一些用于持续存储或共享数据的特性:。
卷的设计目的就是数据的持久化,完全独立于容器的生存周期,因此Docker不会在容器删除时删除其挂载的数据卷。
数据卷的特点:
卷技术小结:容器的持久化和同步操作,容器之间也可以进行数据的共享
方式一:运行容器,指定挂载数据卷命令:
docker run -it -v 主机目录:容器目录
将主机目录/home/test和容器/home建立数据卷
docker run -it -v /home/test:/home centos /bin/bash
可以发现,home目录下多了test这个文件夹,接下来,容器里面的home目录下的内容都会自动同步到宿主机下的 /home/test目录,在宿主机的内容也会自动同步到容器内
查看是否挂载成功
[root@VM-20-17-centos home]# docker inspect df7f51983d11(这个是容器id)
①在容器内部创建一个文件
[root@df7f51983d11 home]# touch test.java
[root@df7f51983d11 home]# ls
test.java
在宿主机的test下查看
[root@VM-20-17-centos home]# cd test
[root@VM-20-17-centos test]# ls
test.java
②在宿主机添加文件
[root@VM-20-17-centos test]# touch test02.java
在容器内部查看
[root@df7f51983d11 home]# ls
test.java test02.java
退出容器 (退出容器后,宿主机的操作依旧会同步到容器)
[root@df7f51983d11 home]# exit
exit
小技巧:通过同步之后,以后只需要在宿主机修改配置文件,容器内的配置就会自动同步,而不需要每次都进入容器去修改配置
(这里宿主机如果已经有安装过mysql的话,很可能发生冲突,很大可能是本机挂载的配置文件中已有文件,将容器中的配置给覆盖了,我们将相应的本机文件中的文件配置删除即可)
[root@VM-20-17-centos ~]# docker pull mysql:5.7 #拉取镜像
# 运行容器,需要做数据挂载
# 安装启动mysql,需要配置mysql的密码,不然启动不了
# 官方 docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
# -v 数据卷挂载,下面的命令是挂载mysql的配置文件 conf.d和mysql的数据文件 data,并且给mysql设置密码
# -e 环境配置
# --name 容器名字
# 开的端口号记得去阿里云的安全组打开
docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
# 启动成功之后,我这里是在本地使用navicat来连接测试
# navicat连接到服务器的3310端口 ,3310和容器内的3306端口映射,然后成功连接
docker rm -f mysql01 #就算把容器删除,宿主机本地的数据依旧还在。如果是在容器内部进行删除数据的操作,那么宿主机就会同步删除,但这里是直接把整个容器删掉,是容器外部的操作,所以宿主机的数据还是会存在的
匿名挂载就是在指定数据卷的时候,不指定容器路径对应的主机路径,这样对应映射的主机路径就是默认的路径/var/lib/docker/volumes/中自动生成一个随机命名的文件夹。
如下运行并匿名挂载Nginx容器:
# -P (大写P表示随机映射端口)
# -v后面如果只有一个路径,那就是容器内部的路径。(不指定宿主机的路径的话,宿主机会自动生成目录)
[root@VM-20-17-centos ~]# docker run -d -P --name nginx01 -v /etc/nginx nginx
# 查看所有的数据卷volume的情况, VOLUME NAME这里的值是真实存在的目录。( VOLUME NAME的值是一串数字和字母,所以称之为匿名挂载)
[root@VM-20-17-centos ~]# docker volume ls
DRIVER VOLUME NAME
local 0736e4097e5bb9b62b24e5f51088b37cf8271df9edd4f8ff1c8f3284fce72983
# 查看匿名挂载的卷在宿主机中的位置
[root@VM-20-17-centos ~]# docker volume inspect 0736e4097e5bb9b62b24e5f51088b37cf8271df9edd4f8ff1c8f3284fce72983
[
{
"CreatedAt": "2022-04-26T08:50:12+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/0736e4097e5bb9b62b24e5f51088b37cf8271df9edd4f8ff1c8f3284fce72983/_data",
"Name": "0736e4097e5bb9b62b24e5f51088b37cf8271df9edd4f8ff1c8f3284fce72983",
"Options": null,
"Scope": "local"
}
]
具名挂载,就是指定文件夹名称,区别于指定路径挂载,这里的指定文件夹名称是在Docker指定的默认数据卷路径下的。通过docker volume ls
命令可以查看当前数据卷的目录情况。
# 通过 -v 卷名:容器内路径 ,这种方式来指定卷的名字,注意这里juming-nginx前面是没有/的,如果带了/,那就变成路径而不是名字了
[root@VM-20-17-centos ~]# docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
629b1917332cc9f8529e8ea785c75aa3be813e21b41b0a05c9f795a254f85caf
[root@VM-20-17-centos ~]# docker volume ls
DRIVER VOLUME NAME
local 0736e4097e5bb9b62b24e5f51088b37cf8271df9edd4f8ff1c8f3284fce72983
local juming-nginx
查看指定的数据卷信息的命令:docker volume inspect数据卷名称
[root@VM-20-17-centos ~]# docker volume inspect juming-nginx
[
{
"CreatedAt": "2022-04-26T08:54:52+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/juming-nginx/_data",
"Name": "juming-nginx",
"Options": null,
"Scope": "local"
}
]
可以看到主机数据卷挂载在/var/lib/docker/volumes/juming-nginx/_data上
Docker所有的数据卷默认在/var/lib/docker/volumes/ 目录下
[root@VM-20-17-centos ~]# cd /var/lib/docker/volumes
[root@VM-20-17-centos volumes]# ls
0736e4097e5bb9b62b24e5f51088b37cf8271df9edd4f8ff1c8f3284fce72983 backingFsBlockDev juming-nginx metadata.db
匿名挂载,具名挂载,指定路径挂载的命令区别如下:
-v 容器内路径 #匿名挂载
-v 卷名:容器内路径 #具名挂载
-v /宿主机路径:容器内路径 #指定路径挂载
指定数据卷映射的相关参数:
ro —— readonly 只读。设置了只读则只能操作宿主机的路径,不能操作容器中的对应路径(在容器内部无法操作)。
rw ----- readwrite 可读可写
[root@VM-20-17-centos ~]# docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:ro nginx
[root@VM-20-17-centos ~]# docker run -d -P --name nginx02 -v juming-ngin
DockerFile就是用来构建docker镜像的构建文件。
前面我们也用的是docker run的方式进行挂载,我们还可以在Dockerfile中使用VOLUME指令来给镜像添加一个或多个数据卷。
[root@VM-20-17-centos home]# mkdir docker-test-volume
[root@VM-20-17-centos home]# ls
docker-test-volume lighthouse test
[root@VM-20-17-centos docker-test-volume]# vim dockerfile1
使用Dockerfile构建一个新的镜像,dockerfile1文件的内容,匿名挂载了volume01和volume02两个目录
# 创建一个dockerFile文件,这里每个命令,就是镜像的每一层
FROM centos
VOLUME ["volume01","volume02"]
CMD echo "----end----"
CMD /bin/bash
# 构建镜像
[root@VM-20-17-centos docker-test-volume]# docker build -f /home/docker-test-volume/dockerfile1 -t jackson/centos:1.0 .
Sending build context to Docker daemon 2.048kB
Step 1/4 : FROM centos
---> 5d0da3dc9764
Step 2/4 : VOLUME ["volume01","volume02"]
---> Running in 964276445ecc
Removing intermediate container 964276445ecc
---> 1ffae309159a
Step 3/4 : CMD echo "----end----"
---> Running in 1a48788e5f5d
Removing intermediate container 1a48788e5f5d
---> 905494613c71
Step 4/4 : CMD /bin/bash
---> Running in 5079de04d995
Removing intermediate container 5079de04d995
---> 556edf4fffd4
Successfully built 556edf4fffd4
Successfully tagged jackson/centos:1.0
# 查看镜像
[root@VM-20-17-centos docker-test-volume]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
jackson/centos 1.0 556edf4fffd4 44 seconds ago 231MB
nginx latest fa5269854a5e 5 days ago 142MB
mysql 5.7 82d2d47667cf 5 days ago 450MB
centos latest 5d0da3dc9764 7 months ago 231MB
[root@VM-20-17-centos docker-test-volume]# docker run -it 556edf4fffd4 /bin/bash
# 可以发现,刚刚挂载的两个目录volume01和volume02已经生成
[root@a6ddee3ff853 /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var volume01 volume02
可以发现,多了两个匿名卷(要运行容器才会生成,如果镜像刚生成,还没运行,那么这两个目录是不会有的,这两个目录是在运行容器的时候才生成的。当然,此后不用运行容器,这两个目录也会存在了,因为已经生成过了)
如果构建镜像的时候没有挂载卷,那就得手动挂载, -v 卷名:容器内路径
容器之间的数据共享,可以通过容器数据卷
容器数据卷是指建立数据卷,来同步多个容器间的数据,实现容器间的数据同步。
首先启动容器1,volume01、volume02为挂载目录。
[root@VM-20-17-centos docker-test-volume]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
jackson/centos 1.0 556edf4fffd4 25 minutes ago 231MB
nginx latest fa5269854a5e 5 days ago 142MB
mysql 5.7 82d2d47667cf 5 days ago 450MB
centos latest 5d0da3dc9764 7 months ago 231MB
# 之前构建镜像的时候写了版本号,这里启动的时候记得加上版本号,否则就会去docker仓库中找最新的
[root@VM-20-17-centos docker-test-volume]# docker run -it --name docker01 jackson/centos:1.0
然后启动容器2,通过参数--volumes-from
,设置容器2和容器1建立数据卷挂载关系。
[root@VM-20-17-centos ~]# docker run -it --name docker02 --volumes-from docker01 jackson/centos:1.0
# 可以看到,容器2与容器1建立挂载关系后,可以看到容器2也有volume01和volume02
[root@d3fe059ecdb9 /]# ls -l
total 56
lrwxrwxrwx 1 root root 7 Nov 3 2020 bin -> usr/bin
drwxr-xr-x 5 root root 360 Apr 26 01:50 dev
drwxr-xr-x 1 root root 4096 Apr 26 01:50 etc
drwxr-xr-x 2 root root 4096 Nov 3 2020 home
lrwxrwxrwx 1 root root 7 Nov 3 2020 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Nov 3 2020 lib64 -> usr/lib64
drwx------ 2 root root 4096 Sep 15 2021 lost+found
drwxr-xr-x 2 root root 4096 Nov 3 2020 media
drwxr-xr-x 2 root root 4096 Nov 3 2020 mnt
drwxr-xr-x 2 root root 4096 Nov 3 2020 opt
dr-xr-xr-x 133 root root 0 Apr 26 01:50 proc
dr-xr-x--- 2 root root 4096 Sep 15 2021 root
drwxr-xr-x 11 root root 4096 Sep 15 2021 run
lrwxrwxrwx 1 root root 8 Nov 3 2020 sbin -> usr/sbin
drwxr-xr-x 2 root root 4096 Nov 3 2020 srv
dr-xr-xr-x 13 root root 0 Apr 26 01:50 sys
drwxrwxrwt 7 root root 4096 Sep 15 2021 tmp
drwxr-xr-x 12 root root 4096 Sep 15 2021 usr
drwxr-xr-x 20 root root 4096 Sep 15 2021 var
drwxr-xr-x 2 root root 4096 Apr 26 01:47 volume01
drwxr-xr-x 2 root root 4096 Apr 26 01:47 volume02
首先在容器1中的volume01中添加文件
[root@VM-20-17-centos ~]# docker attach 494b049dd247
[root@494b049dd247 /]# cd volume01
[root@494b049dd247 volume01]# ls
[root@494b049dd247 volume01]# touch docker01
然后就可以看到容器2的文件也会添加上了
[root@d3fe059ecdb9 /]# cd volume01
[root@d3fe059ecdb9 volume01]# ls
docker01
反过来也是一样的,在容器2的volume01中添加文件,容器1也会相应添加上
# 把容器3与容器1建立挂载,然后在容器3中建立新文件
[root@VM-20-17-centos ~]# docker run -it --name docker03 --volumes-from docker01 jackson/centos:1.0
[root@e5a6f37b1f9b /]# cd volume01
[root@e5a6f37b1f9b volume01]# touch docker03
# 容器1也有docker03这个文件
[root@494b049dd247 volume01]# ls
docker01 docker02 docker03
# 容器2也有docker03这个文件
[root@d3fe059ecdb9 volume01]# ls
docker01 docker02 docker03
# 把容器1删掉
[root@VM-20-17-centos ~]# docker rm -f 494b049dd247
494b049dd247
# 容器2中的文件依旧在
[root@d3fe059ecdb9 volume01]# ls
docker01 docker02 docker03
# 容器3中的文件依旧在
[root@e5a6f37b1f9b volume01]# ls
docker01 docker02 docker03
(这个地方狂神貌似讲的不是很对,他说是拷贝,弹幕里面争议很大,以下仅代表我个人的理解)
# 可以理解为三个容器都共用了宿主机中的匿名数据卷中的文件,把宿主机上的文件删了,两个容器里面的文件也会跟着丢失
[root@VM-20-17-centos volumes]# ls
0736e4097e5bb9b62b24e5f51088b37cf8271df9edd4f8ff1c8f3284fce72983 backingFsBlockDev juming-nginx
240e74fe33512e3182a5224fdc1013d753f6f77c81714781826c8d00ae71cc68 df748d8c94d65e44af403da44db9c4fbcdae4c55e34d5c3ce57d6a6a7eca994e metadata.db
91d3af6b1c1d35b58661ce6d5a3dfed2a251391b24b608e8568bb8fad0c59471 ebc728173eae10e435811c111272f5f5a0c8bc8b365065b63a75a0660efd3668
[root@VM-20-17-centos volumes]# cd 91d3af6b1c1d35b58661ce6d5a3dfed2a251391b24b608e8568bb8fad0c59471/
[root@VM-20-17-centos 91d3af6b1c1d35b58661ce6d5a3dfed2a251391b24b608e8568bb8fad0c59471]# ls
_data
[root@VM-20-17-centos 91d3af6b1c1d35b58661ce6d5a3dfed2a251391b24b608e8568bb8fad0c59471]# cd _data/
[root@VM-20-17-centos _data]# ls
docker01 docker02 docker03
[root@VM-20-17-centos _data]# rm -r docker01
rm: remove regular empty file ‘docker01’? y
# 容器3中文件也跟着被删除了
[root@e5a6f37b1f9b volume01]# ls
docker02 docker03
# 容器2也是一样
[root@d3fe059ecdb9 volume01]# ls
docker02 docker03
# 查看容器3和容器2的挂载目录,可以发现volume01挂载的都是主机中的同一个目录
[root@VM-20-17-centos _data]# docker inspect e5a6f37b1f9b #查看容器3的挂载目录
"Mounts": [
{
"Type": "volume",
"Name": "91d3af6b1c1d35b58661ce6d5a3dfed2a251391b24b608e8568bb8fad0c59471",
"Source": "/var/lib/docker/volumes/91d3af6b1c1d35b58661ce6d5a3dfed2a251391b24b608e8568bb8fad0c59471/_data",
"Destination": "volume01",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
},
{
"Type": "volume",
"Name": "df748d8c94d65e44af403da44db9c4fbcdae4c55e34d5c3ce57d6a6a7eca994e",
"Source": "/var/lib/docker/volumes/df748d8c94d65e44af403da44db9c4fbcdae4c55e34d5c3ce57d6a6a7eca994e/_data",
"Destination": "volume02",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
# 查看容器2的挂载目录
[root@VM-20-17-centos _data]# docker inspect d3fe059ecdb9
"Mounts": [
{
"Type": "volume",
"Name": "df748d8c94d65e44af403da44db9c4fbcdae4c55e34d5c3ce57d6a6a7eca994e",
"Source": "/var/lib/docker/volumes/df748d8c94d65e44af403da44db9c4fbcdae4c55e34d5c3ce57d6a6a7eca994e/_data",
"Destination": "volume02",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
},
{
"Type": "volume",
"Name": "91d3af6b1c1d35b58661ce6d5a3dfed2a251391b24b608e8568bb8fad0c59471",
"Source": "/var/lib/docker/volumes/91d3af6b1c1d35b58661ce6d5a3dfed2a251391b24b608e8568bb8fad0c59471/_data",
"Destination": "volume01",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
# 在主机中新增文件
root@VM-20-17-centos _data]# cd /var/lib/docker/volumes/91d3af6b1c1d35b58661ce6d5a3dfed2a251391b24b608e8568bb8fad0c59471/_data
[root@VM-20-17-centos _data]# ls
docker02 docker03
[root@VM-20-17-centos _data]# touch zhuji
# 可以看到容器3也对应添加了文件
[root@VM-20-17-centos ~]# docker attach e5a6f37b1f9b
[root@e5a6f37b1f9b volume01]# ls
docker02 docker03 zhuji
下面同步两个MySQL的数据库和配置文件,与上面的操作相同,首先建立数据卷,然后给另一个MySQL容器建立容器数据卷挂载,两个mysql不要像狂神那样映射到主机的同一个端口,要映射两个不同的主机端口,否则会冲突。示例如下
[root@VM-20-17-centos _data]# docker run -d -p 6603:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
[root@VM-20-17-centos _data]# docker run -d -p 6604:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01 mysql:5.7
小结:容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止。但是一旦持久化到了本地,这个时候,本地的数据是不会删除的。
Dockerfile是用来构建Docker镜像的文本文件,也可以说是命令参数脚本。docker build
命令用于从Dockerfile构建镜像。可以在docker build
命令中使用 -f 标志指向文件系统中任何位置的Dockerfile。
Docker镜像发布的步骤:
1、编写一个dockerfile文件
2、docker build 构建成为一个镜像
3、docker run 镜像 (运行镜像)
4、docker push 镜像(发布镜像到DockerHub、阿里云镜像仓库)
指令 | 说明 |
---|---|
FROM | 指定基础镜像 |
MAINTAINER | 镜像是谁写的,姓名+邮箱 |
RUN | 镜像构建的时候需要运行的命令 |
ADD | 将本地文件添加到容器中,tar类型文件会自动解压(网络压缩资源不会被解压),可以访问网络资源,类似wget |
WORKDIR | 镜像的工作目录 |
VOLUME | 挂载的目录 |
EXPOSE | 保留端口配置 |
CMD | 指定这个容器启动的时候要运行的命令(只有最后一个会生效,可被替代)。 |
EMTRYPOINT | 指定这个容器启动的时候要运行的命令,可以追加命令 |
ONBUILD | 当构建一个被继承DockerFile,这个时候就会运行ONBUILD的指令,触发指令 |
COPY | 功能类似ADD,但是是不会自动解压文件,也不能访问网络资源 |
ENV | 构建的时候设置环境变量 |
一个形象的解释各个指令作用的图:
Dockerfile 一般分为四部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令,’#’ 为 Dockerfile 中的注释。
关于DockerFile文件的脚本注意点有:
1、每个保留关键字(指令)都必须是大写字母
2、文件中的指令从上到下顺序执行,第一个指令必须是FROM
3、# 号表示注释
4、每一个指令都会创建提交一个新的镜像层,并提交!
关于Dockerfile指令的详细语法解释:Dockerfile文件详解
Dockerfile指令介绍的官方文档:https://docs.docker.com/engine/reference/builder/
DockerFile:构建文件,定义了一切的步骤,源代码
DockerImages:通过DockerFile构建生成的镜像,最终发布和运行的产品
Docker容器:容器就是镜像运行起来 并提供服务
# 1、编写配置文件
[root@VM-20-17-centos home]# mkdir dockerfile
[root@VM-20-17-centos home]# ls
dockerfile docker-test-volume lighthouse mysql test
[root@VM-20-17-centos dockerfile]# vim mydockerfile-centos
[root@VM-20-17-centos dockerfile]# cat mydockerfile-centos
FROM centos
MAINTAINER ethan<1258398543@qq.com>
ENV MYPATH /usr/local
WORKDIR $MYPATH
RUN yum -y install vim
RUN yum -y install net-tools
EXPOSE 80
CMD echo $MYPATH
CMD echo "---end---"
CMD /bin/bash
逐行解释该Dockerfile文件的指令:
通过这个dockerfile构建镜像,构建镜像命令:docker build -f dockerfile文件路径 -t 镜像名[:版本号] .
(这里有个小点.)
上面命令中,-t
参数用来指定 image 文件的名字,后面还可以用冒号指定标签。如果不指定,默认的标签就是latest。最后的那个点表示 Dockerfile 文件所在的路径,上例是当前路径,所以是一个点。
下面执行build命令生成image文件,如果执行成功,可以通过docker images来查看新生成的镜像文件。
# 2、通过这个文件构建镜像
docker build -f mydockerfile-centos -t mycentos:0.1 .
如果有报错跟我一样的 Error: Failed to download metadata for repo ‘appstream’: Cannot prepare internal mirrorlist: No URLs in mirrorlist
我这里宿主机是centos7,可能是docker拉取到的centos镜像版本跟我宿主机不一样,网上有人说好像是因为build的时候 yum默认使用的是宿主机上的,因为centos的版本不一样,导致的yum失败。
FROM centos:7 # 在这里给centos加个跟宿主机centos版本一样的版本号
MAINTAINER ethan<1258398543@qq.com>
ENV MYPATH /usr/local
WORKDIR $MYPATH
RUN yum -y install vim
RUN yum -y install net-tools
EXPOSE 80
CMD echo $MYPATH
CMD echo "---end---"
CMD /bin/bash
# 重新执行一下 docker build -f mydockerfile-centos -t mycentos:0.1 .
Successfully built 57e9eb8b444b
Successfully tagged mycentos01:0.1
# 3、测试运行
[root@VM-20-17-centos dockerfile]# docker run -it mycentos01:0.1
[root@1e0199d8fb38 local]# ls
bin etc games include lib lib64 libexec sbin share src
[root@1e0199d8fb38 local]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.5 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:ac:11:00:05 txqueuelen 0 (Ethernet)
RX packets 7 bytes 586 (586.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
[root@1e0199d8fb38 local]# pwd
/usr/local
以上就是我们自己构建的镜像
以下的镜像是拉取的centos镜像
# docker history 镜像id ,来查看某个镜像的构建过程
[root@VM-20-17-centos ~]# docker history 57e9eb8b444b
IMAGE CREATED CREATED BY SIZE COMMENT
57e9eb8b444b 9 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "/bin… 0B
6cffa0f5104b 9 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B
31e18cb4b83e 9 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B
d3df5b1d3108 9 minutes ago /bin/sh -c #(nop) EXPOSE 80 0B
09063d4813a7 9 minutes ago /bin/sh -c yum -y install net-tools 166MB
aa793ff00e9a 9 minutes ago /bin/sh -c yum -y install vim 221MB
4fa5a8baba8e 9 minutes ago /bin/sh -c #(nop) WORKDIR /usr/local 0B
ac68d7db82d8 9 minutes ago /bin/sh -c #(nop) ENV MYPATH=/usr/local 0B
5778f439503c 9 minutes ago /bin/sh -c #(nop) MAINTAINER Kay<2041290842… 0B
eeb6ee3f44bd 7 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 7 months ago /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B
<missing> 7 months ago /bin/sh -c #(nop) ADD file:b3ebbe8bd304723d4… 204MB
RUN命令与CMD命令的区别在哪里?
简单说,RUN命令在 image 文件的构建阶段执行,执行结果都会打包进入 image 文件;CMD命令则是在容器启动后执行。另外,一个 Dockerfile 可以包含多个RUN命令,但是只能有一个CMD命令。
注意,指定了CMD命令以后,docker container run命令就不能附加命令了(比如前面的/bin/bash),否则它会覆盖CMD命令。
CMD和ENTRYPOINT的区别在哪里?
以下是CMD命令测试
[root@VM-20-17-centos dockerfile]# vim dockerfile-cmd-test
[root@VM-20-17-centos dockerfile]# cat dockerfile-cmd-test
FROM centos
CMD ["ls","-a"]
[root@VM-20-17-centos dockerfile]# docker build -f dockerfile-cmd-test -t cmdtest:1.0 .
Sending build context to Docker daemon 3.072kB
Step 1/2 : FROM centos
---> 5d0da3dc9764
Step 2/2 : CMD ["ls","-a"]
---> Running in 4023b35004c1
Removing intermediate container 4023b35004c1
---> 19977d0ee131
Successfully built 19977d0ee131
Successfully tagged cmdtest:1.0
[root@VM-20-17-centos dockerfile]# docker run 19977d0ee131
.
..
.dockerenv
bin
dev
etc
home
lib
lib64
lost+found
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
# 想追加命令 -l,但是CMD不给,会报错 ,因为-l不是一个完整的命令 ,应该是ls -l
[root@VM-20-17-centos dockerfile]# docker run 19977d0ee131 -l
docker: Error response from daemon: failed to create shim: OCI runtime create failed: container_linux.go:380: starting container process caused: exec: "-l": executable file not found in $PATH: unknown.
ERRO[0000] error waiting for container: context canceled
# 想追加命令 ls -l ,可以发现它直接把原先的ls -a替换掉了,而不是追加上去的
[root@VM-20-17-centos dockerfile]# docker run 19977d0ee131 ls -l
total 48
lrwxrwxrwx 1 root root 7 Nov 3 2020 bin -> usr/bin
drwxr-xr-x 5 root root 340 Apr 26 08:00 dev
drwxr-xr-x 1 root root 4096 Apr 26 08:00 etc
drwxr-xr-x 2 root root 4096 Nov 3 2020 home
lrwxrwxrwx 1 root root 7 Nov 3 2020 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Nov 3 2020 lib64 -> usr/lib64
drwx------ 2 root root 4096 Sep 15 2021 lost+found
drwxr-xr-x 2 root root 4096 Nov 3 2020 media
drwxr-xr-x 2 root root 4096 Nov 3 2020 mnt
drwxr-xr-x 2 root root 4096 Nov 3 2020 opt
dr-xr-xr-x 117 root root 0 Apr 26 08:00 proc
dr-xr-x--- 2 root root 4096 Sep 15 2021 root
drwxr-xr-x 11 root root 4096 Sep 15 2021 run
lrwxrwxrwx 1 root root 8 Nov 3 2020 sbin -> usr/sbin
drwxr-xr-x 2 root root 4096 Nov 3 2020 srv
dr-xr-xr-x 13 root root 0 Apr 26 01:51 sys
drwxrwxrwt 7 root root 4096 Sep 15 2021 tmp
drwxr-xr-x 12 root root 4096 Sep 15 2021 usr
drwxr-xr-x 20 root root 4096 Sep 15 2021 var
以下是entryPoint的测试
[root@VM-20-17-centos dockerfile]# cat dockerfile-cmd-entrypoint
FROM centos
ENTRYPOINT ["ls","-a"]
[root@VM-20-17-centos dockerfile]# docker build -f dockerfile-cmd-entrypoint -t myentrypoint:1.0 .
Sending build context to Docker daemon 4.096kB
Step 1/2 : FROM centos
---> 5d0da3dc9764
Step 2/2 : ENTRYPOINT ["ls","-a"]
---> Running in 42bb03a59bce
Removing intermediate container 42bb03a59bce
---> 4b498a87db2f
Successfully built 4b498a87db2f
Successfully tagged myentrypoint:1.0
[root@VM-20-17-centos dockerfile]# docker run 4b498a87db2f
.
..
.dockerenv
bin
dev
etc
home
lib
lib64
lost+found
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
# 可以发现,是可以直接追加命令的,而不需要完整的命令
[root@VM-20-17-centos dockerfile]# docker run 4b498a87db2f -l
total 56
drwxr-xr-x 1 root root 4096 Apr 26 08:05 .
drwxr-xr-x 1 root root 4096 Apr 26 08:05 ..
-rwxr-xr-x 1 root root 0 Apr 26 08:05 .dockerenv
lrwxrwxrwx 1 root root 7 Nov 3 2020 bin -> usr/bin
drwxr-xr-x 5 root root 340 Apr 26 08:05 dev
drwxr-xr-x 1 root root 4096 Apr 26 08:05 etc
drwxr-xr-x 2 root root 4096 Nov 3 2020 home
lrwxrwxrwx 1 root root 7 Nov 3 2020 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Nov 3 2020 lib64 -> usr/lib64
drwx------ 2 root root 4096 Sep 15 2021 lost+found
drwxr-xr-x 2 root root 4096 Nov 3 2020 media
drwxr-xr-x 2 root root 4096 Nov 3 2020 mnt
drwxr-xr-x 2 root root 4096 Nov 3 2020 opt
dr-xr-xr-x 115 root root 0 Apr 26 08:05 proc
dr-xr-x--- 2 root root 4096 Sep 15 2021 root
drwxr-xr-x 11 root root 4096 Sep 15 2021 run
lrwxrwxrwx 1 root root 8 Nov 3 2020 sbin -> usr/sbin
drwxr-xr-x 2 root root 4096 Nov 3 2020 srv
dr-xr-xr-x 13 root root 0 Apr 26 01:51 sys
drwxrwxrwt 7 root root 4096 Sep 15 2021 tmp
drwxr-xr-x 12 root root 4096 Sep 15 2021 usr
drwxr-xr-x 20 root root 4096 Sep 15 2021 var
1.准备镜像文件tomcat、jdk压缩包
[root@VM-20-17-centos home]# cd mybuild/
[root@VM-20-17-centos mybuild]# touch readme.txt
[root@VM-20-17-centos mybuild]# ls
apache-tomcat-8.5.40.tar.gz jdk-8u192-linux-x64.tar.gz readme.txt
[root@VM-20-17-centos mybuild]#
2.编写dockerfile文件,文件名使用官方命名:Dockerfile ,build的时候会默认寻找当前目录下的文件,不需要使用 -f 参数指定
[root@iZwz99sm8v95sckz8bd2c4Z tomcat]# vim Dockerfile
[root@iZwz99sm8v95sckz8bd2c4Z tomcat]# cat Dockerfile
FROM centos
MAINTAINER ethan<1258398543@qq.com>
COPY readme.txt /usr/local/readme.txt
ADD jdk-8u251-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-8.5.55.tar.gz /usr/local/
RUN yum -y install vim
ENV MYPATH /usr/local
WORKDIR $MYPATH
ENV JAVA_HOME /usr/local/jdk1.8.0_251
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-8.5.55
ENV CATALINA_BASH /usr/local/apache-tomcat-8.5.55
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
EXPOSE 8080
CMD /usr/local/apache-tomcat-8.5.55/bin/startup.sh && tail -F /usr/local/apache-tomcat-8.5.55/bin/logs/catalina.out
3.使用该Dockerfile构建镜像
[root@VM-20-17-centos tomcat]# docker build -t diytomcat .
# 查看镜像
[root@VM-20-17-centos tomcat]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
diytomcat latest 35bd17b5d64f 3 minutes ago 835MB
myentrypoint 1.0 4b498a87db2f About an hour ago 231MB
cmdtest 1.0 19977d0ee131 About an hour ago 231MB
mycentos01 0.1 57e9eb8b444b About an hour ago 591MB
<none> <none> 6d621234391f 2 hours ago 231MB
<none> <none> 84c810a6fabf 2 hours ago 231MB
jackson/centos 1.0 556edf4fffd4 8 hours ago 231MB
nginx latest fa5269854a5e 5 days ago 142MB
mysql 5.7 82d2d47667cf 5 days ago 450MB
centos 7 eeb6ee3f44bd 7 months ago 204MB
centos latest 5d0da3dc9764 7 months ago 231MB
4.启动生成的镜像,构建Tomcat容器.
这里设置了数据卷,宿主机的/home/dockerfile/tomcat/test对应该容器的/usr/local/apache-tomcat-8.5.40/webapps/test。这样关于test项目的修复只需要在宿主机上修改就可以了,不需要进入到容器中修改。
[root@VM-20-17-centos test]# docker run -d -p 8091:8080 --name diytomcat04 -v /home/mybuild/tomcat/test:/usr/local/apache-tomcat-8.5.40/webapps/test diytomcat
b709d703dd5ac5dc00fba6aad9565618c835f965c6ff7ab2000fba1e4c824c55
5.在/home/dockerfile/tomcat/test的目录下,新建index.html 测试Tomcat是否能正常使用。
因为设置了卷挂载所以可以直接在宿主机中进行操作。
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>这是个标题title>
head>
<body>
<h1>这是一个一个简单的HTMLh1>
<p>Hello World!p>
body>
html>
6.访问测试,浏览器访问查看是否能正常访问
1.登录https://hub.docker.com/ DockerHub官网进行注册
2.进行登录,docker login -u 用户名
登录命令
[root@VM-20-17-centos ~]# docker login -u jacksonkkk
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
3.使用docker push
命令推送镜像到DockerHub上的仓库
[root@VM-20-17-centos ~]# docker tag 35bd17b5d64f jacksonkkk/diytomcat:1.0
[root@VM-20-17-centos ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
jacksonkkk/diytomcat 1.0 35bd17b5d64f 3 hours ago 835MB
diytomcat latest 35bd17b5d64f 3 hours ago 835MB
myentrypoint 1.0 4b498a87db2f 4 hours ago 231MB
cmdtest 1.0 19977d0ee131 4 hours ago 231MB
mycentos01 0.1 57e9eb8b444b 4 hours ago 591MB
<none> <none> 6d621234391f 4 hours ago 231MB
<none> <none> 84c810a6fabf 4 hours ago 231MB
jackson/centos 1.0 556edf4fffd4 11 hours ago 231MB
nginx latest fa5269854a5e 6 days ago 142MB
mysql 5.7 82d2d47667cf 6 days ago 450MB
centos 7 eeb6ee3f44bd 7 months ago 204MB
centos latest 5d0da3dc9764 7 months ago 231MB
[root@VM-20-17-centos ~]# docker push jacksonkkk/diytomcat:1.0
因为push的时候,镜像名前面需要加上用户名(jacksonkkk是我的用户名。如果用户名不是当前登录用户则会拒绝push请求),所以需要使用命令docker tag 镜像名 新的镜像名
复制出一份镜像重新打个Tag。(此处我新的镜像名为jacksonkkk/diytomcat )
1.登录阿里云,找到容器镜像服务
2.创建个人实例
3、创建命名空间
4、创建镜像仓库
5、命令行登录阿里云docker仓库(这里涉及个人信息,就不截图了)
6、把镜像push到阿里云上
docker tag 镜像id registry.cn-shenzhen.aliyuncs.com/命名空间/阿里云docker仓库名称:版本号
docker push registry.cn-shenzhen.aliyuncs.com/命名空间/阿里云docker仓库名称:版本号
小结
docker rm -f $(docker ps -aq) # 清空所有容器
docker rmi -f $(docker images -aq) # 清空所有镜像
[root@VM-20-17-centos ~]# docker run -d -P --name tomcat01 tomcat
root@8db5d786b47a:/usr/local/tomcat# apt update && apt install -y iproute2
#查看容器的内部网络地址 ip addr
[root@VM-20-17-centos ~]# docker exec -it tomcat01 ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
74: eth0@if75: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
# Linux主机可以ping通容器内部
[root@VM-20-17-centos ~]# ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.051 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.056 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.060 ms
64 bytes from 172.17.0.2: icmp_seq=4 ttl=64 time=0.052 ms
我们每启动一个docker容器,docker就会给docker容器分配一个ip,Linux下只要安装了docker,就会有一个网卡docker0。
桥接模式,使用的技术是 evth-pair技术
再次输入命令 ip addr,发现多了 一个网卡
# 可以发现启动的容器所带来的网卡,是一对一对的。(容器删除,对应的网卡也会自动删除)
# evth-pair 就是一对虚拟设备接口,他们都是成对出现的,一端连着协议,一端彼此相连
# 正因为这个特性,evth-pair 充当一个桥梁,连接各种虚拟网络设备
# OpenStac 、 Docker容器之间的连接、OVS的连接,都是使用evth-pair技术
测试tomcat02是否能ping通tomcat01
docker exec -it tomcat02 ping 172.17.0.2
结论:tomcat01和tomcat02是共用一个路由器-----docker0
所有的容器不指定网络的情况下,都是docker0路由的,docker会给我们的容器分配一个默认的可用IP
Docker使用的是Linux中的桥接,宿主机是一个Docker容器的网桥----docker0
Docker中的所有网络接口都是虚拟的(虚拟的转发效率高)
来自大佬的小拓展(原文链接:https://blog.csdn.net/huangjhai/article/details/120425457)
使用以下命令查看所有的Docker网络:
docker network ls
Docker默认提供了四个网络模式,说明:
bridge:容器默认的网络是桥接模式(自己搭建的网络默认也是使用桥接模式,启动容器默认也是使用桥接模式)。此模式会为每一个容器分配、设置IP等,并将容器连接到一个docker0虚拟网桥,通过docker0网桥以及Iptables nat表配置与宿主机通信。
none:不配置网络,容器有独立的Network namespace,但并没有对其进行任何网络设置,如分配veth pair 和网桥连接,配置IP等。
host:容器和宿主机共享Network namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。
container:创建的容器不会创建自己的网卡,配置自己的IP容器网络连通。容器和另外一个容器共享Network namespace(共享IP、端口范围)。
容器默认使用bridge网络模式,我们使用该docker run --network=选项指定容器使用的网络:
host模式:使用 --net=host 指定。
none模式:使用 --net=none 指定。
bridge模式:使用 --net=bridge 指定,默认设置。
container模式:使用 --net=container:NAME_or_ID 指定。
Namespace的简要说明:
Docker使用了Linux的Namespaces技术来进行资源隔离,如PID Namespace隔离进程,Mount Namespace隔离文件系统,Network Namespace隔离网络等。
一个Network Namespace提供了一份独立的网络环境,包括网卡、路由、Iptable规则等都与其他的NetworkNamespace隔离。一个Docker容器一般会分配一个独立的Network Namespace。
如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。
使用host模式的容器可以直接使用宿主机的IP地址与外界通信,容器内部的服务端口也可以使用宿主机的端口,不需要进行NAT,host最大的优势就是网络性能比较好,但是docker host上已经使用的端口就不能再用了,网络的隔离性不好。Host模式的模型图,如下图所示:
备注:eth0为宿主机的10.126.130.4为宿主机的内网地址。
这个模式指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信。Container模式模型示意图如下:
使用none模式,Docker容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息。需要我们自己为Docker容器添加网卡、配置IP等。
这种网络模式下容器只有lo回环网络,没有其他网卡。none模式可以在容器创建时通过–network=none来指定。这种类型的网络没有办法联网,封闭的网络能很好的保证容器的安全性。
None模式示意图:
当Docker进程启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。
从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。在主机上创建一对虚拟网卡veth pair设备,Docker将veth pair设备的一端放在新创建的容器中,并命名为eth0(容器的网卡),另一端放在主机中,以vethxxx这样类似的名字命名,并将这个网络设备加入到docker0网桥中。可以通过brctl show命令查看。
bridge模式是docker的默认网络模式,不写–net参数,就是bridge模式。使用docker run -p时,docker实际是在iptables做了DNAT规则,实现端口转发功能。可以使用iptables -t nat -vnL查看。bridge模式如下图所示:
当Docker server启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器会连接到这个虚拟网桥上。Docker0使用到的技术是evth-pair技术。在默认bridge网络模式下,我们每启动一个Docker容器,Docker就会给Docker容器配置一个ip。
Docker容器完成bridge网络配置的过程如下:
(–link现在已经不推荐使用,了解即可)
在微服务部署的场景下,注册中心是使用服务名来唯一识别微服务的,而我们上线部署的时候微服务对应的IP地址可能会改动,所以我们需要使用容器名来配置容器间的网络连接。使用–link可以完成这个功能。
ping如果是报错的OCI的,记得先进容器内部执行,之所以会报错是因为这里的tomcat没有ping这个命令,需要先安装 apt update && apt install -y net-tools
# 通过--link让容器之间互相ping通
docker run -d -P --name tomcat03 --link tomcat02 tomcat
docker exec -it tomcat03 /bin/bash # 进入容器内部
apt update && apt install -y net-tools # 安装ping命令所依赖的包
apt-get update
apt install iputils-ping
apt update && apt install -y iproute2 # 安装ip addr命令依赖的包
# docker exec -it tomcat03 ping tomcat02
[root@VM-20-17-centos ~]# docker exec -it tomcat03 ping tomcat02
PING tomcat02 (172.17.0.3) 56(84) bytes of data.
64 bytes from tomcat02 (172.17.0.3): icmp_seq=1 ttl=64 time=0.097 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.074 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=3 ttl=64 time=0.051 ms
# 反向ping,发现ping不通
# docker exec -it tomcat02 ping tomcat03
[root@VM-20-17-centos ~]# docker exec -it tomcat02 ping tomcat03
ping: tomcat03: Name or service not known
[root@VM-20-17-centos ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
09fb7082262f bridge bridge local
3571c95cd476 host host local
f43080225231 none null local
# docker network inspect 桥接网络id
[root@VM-20-17-centos ~]# docker network inspect 09fb7082262f
–link的原理:就是在外面的hosts配置中增加了一个 172.17.0.3 tomcat02 a3f54784bc41 映射
[root@VM-20-17-centos ~]# docker exec -it tomcat03 cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.3 tomcat02 a3f54784bc41 #tomcat03 可以ping 通tomcat02的原因,因为配置文件写好了,只要请求tomcat02,直接就转发到172.17.0.3
172.17.0.4 7450b8509942
# 发现02的没有配置03的
[root@VM-20-17-centos ~]# docker exec -it tomcat02 cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.3 a3f54784bc41
因为docker0,默认情况下不能通过容器名进行访问。需要通过–link进行设置连接。这样的操作比较麻烦,更推荐的方式是自定义网络,容器都使用该自定义网络,就可以实现通过容器名来互相访问了。
[root@VM-20-17-centos ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
09fb7082262f bridge bridge local
3571c95cd476 host host local
f43080225231 none null local
# --net bridge 是默认参数,不写也会自动带上的
# docker run -d -P --name tomcat01 --net bridge tomcat
[root@VM-20-17-centos ~]# docker network create --help
Usage: docker network create [OPTIONS] NETWORK
Create a network
Options:
--attachable Enable manual container attachment
--aux-address map Auxiliary IPv4 or IPv6 addresses used by Network driver (default map[])
--config-from string The network from which to copy the configuration
--config-only Create a configuration only network
-d, --driver string Driver to manage the Network (default "bridge")
--gateway strings IPv4 or IPv6 Gateway for the master subnet
--ingress Create swarm routing-mesh network
--internal Restrict external access to the network
--ip-range strings Allocate container ip from a sub-range
--ipam-driver string IP Address Management Driver (default "default")
--ipam-opt map Set IPAM driver specific options (default map[])
--ipv6 Enable IPv6 networking
--label list Set metadata on a network
-o, --opt map Set driver specific options (default map[])
--scope string Control the network's scope
--subnet strings Subnet in CIDR format that represents a network segment
# 自定义网络
--driver bridge #指定bridge驱动程序来管理网络
--subnet 192.168.0.0/16 #指定网段的CIDR格式的子网
--gateway 192.168.0.1 #指定主子网的IPv4或IPv6网关
[root@VM-20-17-centos ~]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
bd09d0023cc17bb06679eea4a70707f3d0deef462e49a883e849b38ce4bc059a
[root@VM-20-17-centos ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
09fb7082262f bridge bridge local
3571c95cd476 host host local
bd09d0023cc1 mynet bridge local
f43080225231 none null local
[root@VM-20-17-centos ~]# docker network inspect mynet
[
{
"Name": "mynet",
"Id": "bd09d0023cc17bb06679eea4a70707f3d0deef462e49a883e849b38ce4bc059a",
"Created": "2022-04-27T09:11:51.194880776+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.0.0/16",
"Gateway": "192.168.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]
# 下面启动两个容器,指定使用该自定义网络mynet,测试处于自定义网络下的容器,是否可以直接通过容器名进行网络访问。
[root@VM-20-17-centos ~]# docker run -d -P --name tomcat-net-01 --net mynet tomcat
5742920d6a3cafe5d88bca0ef66d2b56d475c887984bd7948e114cc57b915720
[root@VM-20-17-centos ~]# docker run -d -P --name tomcat-net-02 --net mynet tomcat
d50e701c062d2d041728a0422d2c47b9ec6c80aea8b920ee32d2bb9674eca624
[root@VM-20-17-centos ~]# docker network inspect mynet
"Containers": {
"5742920d6a3cafe5d88bca0ef66d2b56d475c887984bd7948e114cc57b915720": {
"Name": "tomcat-net-01",
"EndpointID": "690a2421dcef5530238b37487ed2c879db8a8f776388bf3e0444a8914576ca57",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/16",
"IPv6Address": ""
},
"d50e701c062d2d041728a0422d2c47b9ec6c80aea8b920ee32d2bb9674eca624": {
"Name": "tomcat-net-02",
"EndpointID": "e36caa80fefa8d1a700ed37cad51047db542e5057297435f558161921335d230",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/16",
"IPv6Address": ""
}
},
# 进入01,安装ping命令
[root@VM-20-17-centos ~]# docker exec -it tomcat-net-01/bin/bash
root@5742920d6a3c:/usr/local/tomcat# apt-get update
root@5742920d6a3c:/usr/local/tomcat# apt install iputils-ping
# 进入02,安装ping命令
[root@VM-20-17-centos ~]# docker exec -it tomcat-net-02 /bin/bash
root@d50e701c062d:/usr/local/tomcat# apt-get update
root@d50e701c062d:/usr/local/tomcat# apt install iputils-ping
[root@VM-20-17-centos ~]# docker exec -it tomcat-net-01 ping 192.168.0.3
# 直接通过名字ping通
[root@VM-20-17-centos ~]# docker exec -it tomcat-net-01 ping tomcat-net-02
PING tomcat-net-02 (192.168.0.3) 56(84) bytes of data.
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.057 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.062 ms
^C
--- tomcat-net-02 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.057/0.059/0.062/0.002 ms
# 反过来通过02 ping 01,一样能通
[root@VM-20-17-centos ~]# docker exec -it tomcat-net-02 ping tomcat-net-01
PING tomcat-net-01 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.058 ms
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.057 ms
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=3 ttl=64 time=0.063 ms
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=4 ttl=64 time=0.063 ms
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=5 ttl=64 time=0.078 ms
^C
--- tomcat-net-01 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4000ms
rtt min/avg/max/mdev = 0.057/0.063/0.078/0.007 ms
没有设置的情况下,不同网络间的容器是无法进行网络连接的。如图,两个不同的网络docker0和自定义网络mynet的网络模型图:
在默认网络bridge下启动容器tomcat-01,尝试连接mynet网络下的tomcat-net-01容器。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0YY02lYi-1651031629557)(https://gitee.com/hyxJackson/picturesave/raw/master/a19c48b24b2b4aa8ad5eaa5e0f0bdc9b.png)]
可以看到是无法网络连接的。不同Docker网络之间的容器需要连接的话需要把作为调用方的容器注册一个ip到被调用方所在的网络上。需要使用docker connect
命令。
[root@VM-20-17-centos ~]# docker network connect --help
Usage: docker network connect [OPTIONS] NETWORK CONTAINER
Connect a container to a network
Options:
--alias strings Add network-scoped alias for the container
--driver-opt strings driver options for the network
--ip string IPv4 address (e.g., 172.30.100.104)
--ip6 string IPv6 address (e.g., 2001:db8::33)
--link list Add link to another container
--link-local-ip strings Add a link-local address for the container
# 打通tomcat01 和mynet这个网络
[root@VM-20-17-centos ~]# docker network connect mynet tomcat01
[root@VM-20-17-centos ~]# docker network inspect mynet
# tomcat01这个容器现在就有了两个ip地址
# 可以发现,现在tomcat01已经能打通tomcat-net-01
[root@VM-20-17-centos ~]# docker exec -it tomcat01 ping tomcat-net-01
PING tomcat-net-01 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.064 ms
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.060 ms
^C
--- tomcat-net-01 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 0.060/0.062/0.064/0.002 ms
# tomcat02没有跟mynet这个网络打通,所以依旧无法ping通
[root@VM-20-17-centos ~]# docker exec -it tomcat02 ping tomcat-net-01
ping: tomcat-net-01: Name or service not known
下面部署如图所示的三主三从的Redis集群
# 创建网络名为redis的自定义网络
[root@VM-20-17-centos ~]# docker network create redis --subnet 172.38.0.0/16
941d8f6648642f8f7f210a06d6c0001f1b704e8404a4826849b152d64896fca3
[root@VM-20-17-centos ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
09fb7082262f bridge bridge local
3571c95cd476 host host local
bd09d0023cc1 mynet bridge local
f43080225231 none null local
941d8f664864 redis bridge local
通过以下脚本创建六个redis的配置信息
for port in $(seq 1 6); \
do \
mkdir -p /mydata/redis/node-${port}/conf
touch /mydata/redis/node-${port}/conf/redis.conf
cat << EOF >/mydata/redis/node-${port}/conf/redis.conf
port 6379
bind 0.0.0.0
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.38.0.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done
[root@VM-20-17-centos ~]# cd /mydata/
[root@VM-20-17-centos mydata]# ls
redis
[root@VM-20-17-centos mydata]# cd redis/
[root@VM-20-17-centos redis]# ls
node-1 node-2 node-3 node-4 node-5 node-6
依次启动六个redis,设置对应的容器数据卷挂载
#第1个Redis容器
docker run -p 6371:6379 -p 16371:16379 --name redis-1 \
-v /mydata/redis/node-1/data:/data \
-v /mydata/redis/node-1/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.11 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
#第2个Redis容器
docker run -p 6372:6379 -p 16372:16379 --name redis-2 \
-v /mydata/redis/node-2/data:/data \
-v /mydata/redis/node-2/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.12 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
#第3个Redis容器
docker run -p 6373:6379 -p 16373:16379 --name redis-3 \
-v /mydata/redis/node-3/data:/data \
-v /mydata/redis/node-3/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.13 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
#第4个Redis容器
docker run -p 6374:6379 -p 16374:16379 --name redis-4 \
-v /mydata/redis/node-4/data:/data \
-v /mydata/redis/node-4/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.14 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
#第5个Redis容器
docker run -p 6375:6379 -p 16375:16379 --name redis-5 \
-v /mydata/redis/node-5/data:/data \
-v /mydata/redis/node-5/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.15 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
#第6个Redis容器
docker run -p 6376:6379 -p 16376:16379 --name redis-6 \
-v /mydata/redis/node-6/data:/data \
-v /mydata/redis/node-6/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.16 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
# 日志查看 docker logs redis-1 docker logs redis-2
进入容器
# 这个redis镜像中没有bash,是sh ,这里进入的是redis-1这个容器
[root@VM-20-17-centos redis]# docker exec -it redis-1 /bin/sh
# 创建集群
/data # redis-cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:6379 172.38.0.15:6379 172.38.0.16:6379 --cluster-replicas 1
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
查看集群信息
# redis-cli -c
# cluster info
# cluster nodes
/data # redis-cli -c
127.0.0.1:6379> cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:1
cluster_stats_messages_ping_sent:203
cluster_stats_messages_pong_sent:206
cluster_stats_messages_sent:409
cluster_stats_messages_ping_received:201
cluster_stats_messages_pong_received:203
cluster_stats_messages_meet_received:5
cluster_stats_messages_received:409
127.0.0.1:6379> cluster nodes
1fe798431adf6929e7c4c42dfe68a06cf2afc8fc 172.38.0.12:6379@16379 master - 0 1651026759598 2 connected 5461-10922 # 主机
8772dc6ea9377834bd6478dc705abe6fa3a655f1 172.38.0.14:6379@16379 slave # 从机 24b2f2cf14ad8edc16b336ec539ca38c615f030a 0 1651026759000 4 connected
002d5169ffa41b51d434a53a62388e039fabb3ad 172.38.0.16:6379@16379 slave # 从机 1fe798431adf6929e7c4c42dfe68a06cf2afc8fc 0 1651026758095 6 connected
5859376a31233072e1761c82a43a55d4a4508740 172.38.0.11:6379@16379 myself,master - 0 1651026758000 1 connected 0-5460 # 主机
5edeb5a195a1ae0f0e9b54018312e4f129c5bdab 172.38.0.15:6379@16379 slave # 从机 5859376a31233072e1761c82a43a55d4a4508740 0 1651026760099 5 connected
24b2f2cf14ad8edc16b336ec539ca38c615f030a 172.38.0.13:6379@16379 master - 0 1651026759097 3 connected 10923-16383 # 主机
/data # redis-cli -c
127.0.0.1:6379> set test02 ceshi
-> Redirected to slot [14163] located at 172.38.0.13:6379
OK
[root@VM-20-17-centos ~]# docker stop redis-3
redis-3
#要重进集群,因为当前连的是172.38.0.13的,而正好在刚刚被我们停掉了,所以要重新进入集群,然后再次查看
/data # redis-cli -c
127.0.0.1:6379> get test02
-> Redirected to slot [14163] located at 172.38.0.14:6379
"ceshi"
(1)构建springboot项目
package dockerdemo.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
(2)打包应用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jhek6Er0-1651031629563)(https://gitee.com/hyxJackson/picturesave/raw/master/image-20220427110901736.png)]
(3)编写Dockerfile
FROM java:8
COPY *.jar /app.jar
CMD ["--server.port=8080"]
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app.jar"]
把jar包从taget里面复制出来,因为Dockerfile里面写的是当前目录下的所有jar包,而Dockerfile的当前目录是处于根目录
把jar包和Dockerfile放到服务器某个目录下
(4)构建镜像
[root@VM-20-17-centos springbootdocker]# docker build -t kaydockerdemo .
[root@VM-20-17-centos springbootdocker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
kaydockerdemo latest 946edb0ba69b About a minute ago 661MB
tomcat latest 0183eb12bb0c 29 hours ago 680MB
redis 5.0.9-alpine3.11 3661c84ee9d0 2 years ago 29.8MB
java 8 d23bdf5b1b1b 5 years ago 643MB
(5)发布运行
# 运行容器
[root@VM-20-17-centos springbootdocker]# docker run -d -P --name kay-springboot-web kaydockerdemo
46fb7e19f24c984b137a6b69dc3e9ef0741aad711fd82faf1107f3c74a4d2f3a
[root@VM-20-17-centos springbootdocker]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
46fb7e19f24c kaydockerdemo "java -jar /app.jar …" 43 seconds ago Up 42 seconds 0.0.0.0:49161->8080/tcp, :::49161->8080/tcp kay-springboot-web
[root@VM-20-17-centos springbootdocker]# curl localhost:49161
hello
如果在运行docker期间有进行防火墙操作,那么一定要重启docker
systemctl restart docker
本文是我手敲的狂神docker入门视频的笔记
本文部分内容参考自https://blog.csdn.net/huangjhai/article/details/120425457