Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。
Docker是基于 Go 语言开发的,是一个开源项目。
文档地址:https://docs.docker.com/
仓库地址:https://hub.docker.com/
虚拟机技术缺点:模拟一个完整的操作系统,资源占用多,步骤冗余,启动慢。
Docker 容器化技术:不是模拟的一个完整的操作系统。运行在宿主机的内核上。每个容器内是互相隔离的,互不影响。
DevOps:开发 运维。
应用更快的交付和部署。
传统:安装各种的jar包,打包发布。
Docker :一键打包镜像发布,测试。
更便捷的升级和扩缩容,项目打包为一个镜像,部署应用就和搭积木一样。
更简单的系统运维,容器化后,开发测试环境都是一致的。
更高效的计算资源利用,Docke是内核级的虚拟化,在一个物理机上可以运行很多的容器。
镜像(image):
就好比是一个模板,可通过这个镜像来创建容器服务,比如 tomcat 镜像—>run—>tomcat01容器,通过这个镜像可以创建多个容器(应用最终在容器中运行)。
容器(container):
Docker利用容器技术,独立运行一个或一组应用,通过镜像创建。
启动,停止,删除,基本命令。
仓库(repository):
存放镜像的地方。仓库分为公有仓库和私有仓库。
环境准备:
环境查看
#系统内核是3.0以上的
[root@zhourui /]# uname -r
4.18.0-193.28.1.el8_2.x86_64
#系统版本
[root@zhourui /]# cat /etc/os-release
NAME="CentOS Linux"
VERSION="8 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="8"
PLATFORM_ID="platform:el8"
PRETTY_NAME="CentOS Linux 8 (Core)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:8"
HOME_URL="https://www.centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"
CENTOS_MANTISBT_PROJECT="CentOS-8"
CENTOS_MANTISBT_PROJECT_VERSION="8"
REDHAT_SUPPORT_PRODUCT="centos"
REDHAT_SUPPORT_PRODUCT_VERSION="8"
安装:参考帮助文档 https://docs.docker.com/engine/install/centos/
卸载旧的版本
#卸载
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
#需要的安装包
yum install -y yum-utils
#设置镜像的仓库
yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo #默认的是国外的十分慢
#阿里云镜像 (推荐使用)
yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
#更新yum软件包索引
yun makecache fast
#安装docker decker-ce社区版的 ee企业版
yum install docker-ce docker-ce-cli containerd.io
#启动docker
systemctl start docker
#查看是否安装成功
docker version
#启动 hello-world
docker run hello-world
#查看下载的hello-world镜像
[root@zhourui /]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest d1165f221234 2 weeks ago 13.3kB
#卸载docker
yum remove docker-ce docker-ce-cli containerd.io
#删除资源
rm -rf /var/lib/docker
rm -rf /var/lib/containerd
登录阿里云找到容器服务。
找到容器镜像服务
配置使用
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://tk46rux4.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
流程图
Docker是一个Client,Server结构的系统,Docker的守护进程运行在主机上,通过Socket从客户端访问。
DockerServer接收到DockerClient的指令,就会执行这个命令。
Docker为什么比VNM快:
Docker有比虚拟机更少的抽象层。
Docker利用的是宿主机的内核,VM有自己的Guest OS。
新建一个容器的时候,Docker不需要像虚拟机一样新建一个系统内核。利用宿主机的内核,提升了启动速度和系统资源利用率。
docker -version #显示docker的版本信息
docker info #docker的详细信息 镜像和容器的数量
docker 命令 --help #万能命令
docker --help #docker的所有命令
命令:官网地址 https://docs.docker.com/reference/
**docker images:**查看本机所有镜像
[root@zhourui /]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest d1165f221234 2 weeks ago 13.3kB
#解释
REPOSITORY 镜像的仓库源
TAG 镜像的标签
IMAGE ID 镜像的 id
CREATED 镜像的创建时间
SIZE 镜像的大小
#可选项
-a, --all #显示所有的镜像
-q, --quiet #只显示镜像的id
docker search:搜索镜像
[root@zhourui /]# docker search mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 10634 [OK]
mariadb MariaDB Server is a high performing open sou… 3990 [OK]
#可选项
--filter=STARS=3000 #搜索出来的就是stars大于等于3000的 -f简写
[root@zhourui /]# docker search mysql -f=STARS=3000
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 10634 [OK]
mariadb MariaDB Server is a high performing open sou… 3990 [OK]
docker pull:下载镜像
#下载 docker pull 镜像名 [:tag](可以选版本) 不写版本默认latest最后一个
[root@zhourui /]# docker pull mysql
Using default tag: latest
latest: Pulling from library/mysql
a076a628af6f: Pull complete #分层下载 docker image核心 联合文件系统
f6c208f3f991: Pull complete
88a9455a9165: Pull complete
406c9b8427c6: Pull complete
7c88599c0b25: Pull complete
25b5c6debdaf: Pull complete
43a5816f1617: Pull complete
1a8c919e89bf: Pull complete
9f3cf4bd1a07: Pull complete
80539cea118d: Pull complete
201b3cad54ce: Pull complete
944ba37e1c06: Pull complete
Digest: sha256:feada149cb8ff54eade1336da7c1d080c4a1c7ed82b5e320efb5beebed85ae8c #签名
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest #真实地址
# docker pull mysql
# 等价
# docker pull docker.io/library/mysql:latest
#指定版本下载
[root@zhourui /]# docker pull mysql:5.7
5.7: Pulling from library/mysql
a076a628af6f: Already exists #共用
f6c208f3f991: Already exists
88a9455a9165: Already exists
406c9b8427c6: Already exists
7c88599c0b25: Already exists
25b5c6debdaf: Already exists
43a5816f1617: Already exists
1831ac1245f4: Pull complete
37677b8c1f79: Pull complete
27e4ac3b0f6e: Pull complete
7227baa8c445: Pull complete
Digest: sha256:b3d1eff023f698cd433695c9506171f0d08a8f92a0c8063c1a4d9db9a55808df
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7
[root@zhourui /]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest d1165f221234 2 weeks ago 13.3kB
mysql 5.7 a70d36bc331a 2 months ago 449MB
mysql latest c8562eaf9d81 2 months ago 546MB
docker rmi:删除镜像
#删除指定的容器 根据id
[root@zhourui /]# docker rmi -f c8562eaf9d81
#删除多个镜像
[root@zhourui /]# docker rmi -f id1 id2 id3
#删除全部容器
[root@zhourui /]# docker rmi -f $(docker images -aq)
我们有了镜像才可以创建容器,下载一个CentOS镜像来测试学习。
docker pull centos
新建容器并启动
docker run (可选参数) image
#参数说明
--name=“Name” #容器名字 tomcat01 tomcat01 来区分
-d #后台方式运行
-it #使用交互方式运行,进入容器查看内容
-p #指定容器的端口 -p 8080:8080
-p 主机端口:容器端口 (常用)
-p ip:主机端口:容器端口
-p 容器端口
容器端口(不写-p)
-p #随机指定端口
#启动并进入容器
[root@zhourui /]# docker run -it centos /bin/bash
[root@b728c79b5448 /]# ls #查看容器内的centos 基础版本 很多的命令不完善
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
[root@b728c79b5448 /]# exit #退出命令
exit
[root@zhourui /]# ls
bin boot dev etc home lib lib64 media mnt opt patch proc root run sbin srv sys tmp usr var www
列出所有运行的容器
# docker ps
#列出所有在运行的容器
-a #列出历史运行过的容器
-n=? #显示最近创建的n个容器
-q #列出运行容器的id
[root@zhourui /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@zhourui /]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b728c79b5448 centos "/bin/bash" 4 minutes ago Exited (0) 2 minutes ago relaxed_elbakyan
0ce52f9209e4 d1165f221234 "/hello" 5 hours ago Exited (0) 5 hours ago intelligent_mirzakhani
退出容器
exit #容器停止并退出
ctrl +P +Q #按住这三个键 容器不停止退出
[root@zhourui /]# docker run -it centos /bin/bash
[root@c9797d0b4ba8 /]# [root@zhourui /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c9797d0b4ba8 centos "/bin/bash" About a minute ago Up About a minute inspiring_faraday
删除容器
docker rm #删指定id的容器 不能删除正在运行的容器 强制删除 rm -f
docker rm -f $(docker ps -aq) #删除全部的容器
docker -a-q|xargs docker rm #删除全部容器
启动和停止容器的操作
docker start 容器id #启动
docker restart 容器id #重启
docker stop 容器id #停止容器
docker kill 容器id #强制停止
后台启动容器
# docker run -d 容器名 后台启动
[root@zhourui /]# docker run -d centos
#运行docker ps 发现centos停止了
#docker容器使用后台运行,就必须有一个前台进程,docker发现没有应用,就会自动停止
查看日志
docker logs -f -t --tail 10 容器id #打印最近10条日志
#编写shell脚本
“while true;do echo zhourrrrr;sleep 1;done”
[root@zhourui /]# docker run -d centos /bin/bash -c "while true;do echo zhourrrr;sleep 1;done"
e79bac46e660abb781dcce7b0dbd3a3a896b573a104fdd9a15db0bbf5331341b
[root@zhourui /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e79bac46e660 centos "/bin/bash -c 'while…" 3 seconds ago Up 1 second jolly_sanderson
#显示日志
-tf #显示日志 t 时间
--tail number #最近的多少条数据
[root@zhourui /]# docker logs -f -t --tail 10 e79bac46e660
查看容器中的进程信息
docker top 容器id
[root@zhourui /]# docker top e79bac46e660
UID PID PPID C STIME TTY
root 227610 227588 0 22:36 ?
root 229020 227610 0 22:45 ?
查看镜像源数据
docker inspect 容器id
[root@zhourui /]# docker inspect e79bac46e660
[
{
"Id": "e79bac46e660abb781dcce7b0dbd3a3a896b573a104fdd9a15db0bbf5331341b",
"Created": "2021-03-21T14:36:07.740342428Z",
"Path": "/bin/bash",
"Args": [
"-c",
"while true;do echo zhourrrr;sleep 1;done"
],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 227610,
"ExitCode": 0,
"Error": "",
"StartedAt": "2021-03-21T14:36:08.2053845Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
.........#省略...
}
}
进入当前正在运行的容器
#通常容器都是后台的方式运行的,需要进入容器修改一些配置
#命令
docker exec -it 容器id bashShell(bin/bash)
#测试
[root@zhourui /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
538cddb5e369 centos "bin/bash -c 'while …" 14 seconds ago Up 13 seconds quizzical_wing
[root@zhourui /]# docker exec -it 538cddb5e369 bin/bash
[root@538cddb5e369 /]#
[root@538cddb5e369 /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
[root@538cddb5e369 /]# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 11:08 ? 00:00:00 bin/bash -c while true;do echo zzzzzrr;sleep 2;done
root 66 0 0 11:10 pts/0 00:00:00 bin/bash
root 131 1 0 11:12 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 2
root 132 66 0 11:12 pts/0 00:00:00 ps -ef
#方式二
docker attach 容器id
#测试
[root@zhourui /]# docker attach 538cddb5e369
zzzzzrr
zzzzzrr
zzzzzrr
zzzzzrr
#进去后是正在执行的当前代码,想停止可以新开一个窗口 docker rm -f $(docker ps -aq)
# docker exec 进入后打开了一个新的终端,可以在里面操作
# docker attach 进入容器正在执行的终端,不会启动新的进程
从容器内拷贝文件到主机上
docker cp 容器id:容器内路径 目的主机路径
#测试
[root@zhourui /]# cd /home
[root@zhourui home]# ls
www zhour.java
[root@zhourui home]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
44e87620bf99 centos "/bin/bash" About a minute ago Up About a minute romantic_burnell
#进入容器
[root@zhourui home]# docker attach 44e87620bf99
[root@44e87620bf99 /]# cd /home
[root@44e87620bf99 home]# ls
#在容器内新建一个文件
[root@44e87620bf99 home]# touch zr.java
[root@44e87620bf99 home]# ls
zr.java
[root@44e87620bf99 home]# exit
exit
[root@zhourui home]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@zhourui home]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
44e87620bf99 centos "/bin/bash" 3 minutes ago Exited (0) 6 seconds ago romantic_burnell
#将容器内的文件拷贝到主机上
[root@zhourui home]# docker cp 44e87620bf99:/home/zr.java /home
[root@zhourui home]# ls
www zhour.java zr.java
[root@zhourui home]#
#拷贝是一个手动过程,后面学习使用 -v 卷的技术,可以实现自动同步
常用命令
搜索镜像:docker search nginx
下载镜像:docker pull nginx
运行测试:docker run -d --name nginx01 -p 3344:80 nginx (–name:起别名,-p 3344:80 3344是暴露的端口就是宿主机端口 80是nginx默认端口就是容器的端口)
[root@zhourui home]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest f6d0b4767a6c 2 months ago 133MB
centos latest 300e315adb2f 3 months ago 209MB
hello-world latest bf756fb1ae65 14 months ago 13.3kB
#--name:起别名,-p 3344:80 3344是暴露的端口 80是nginx默认端口
[root@zhourui home]# docker run -d --name nginx01 -p 3344:80 nginx
56b36ad955ca7cf6d80708b20d7ffd1152a0ca974c312df45bfe9e31d0888e0b
[root@zhourui home]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
56b36ad955ca nginx "/docker-entrypoint.…" 7 seconds ago Up 6 seconds 0.0.0.0:3344->80/tcp nginx01
[root@zhourui home]# curl localhost:3344
[root@zhourui home]# docker exec -it nginx01 bin/bash
root@56b36ad955ca:/# whereis nginx
nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx
root@56b36ad955ca:/# cd /etc/nginx
root@56b36ad955ca:/etc/nginx# ls
conf.d fastcgi_params koi-utf koi-win mime.types modules nginx.conf scgi_params uwsgi_params win-utf
root@56b36ad955ca:/etc/nginx#
#每次改动nginx的配置文件,都需要进入容器的内部修改,非常麻烦,后面学习数据卷的技术就可以在容器外部修改文件,容器内自动同步。
访问自己服务器的nginx:http://39.105.48.232:3344/(前提是自己阿里云服务器安全组中开启了3344端口)
#docker hub 官方的使用
docker run -it --rm tomcat:9.0
#之前练习的启动在后台,停止容器后,容器还在,可以查到。run -it --rm 一般用来测试,用完即删除(容器删除镜像还在)
[root@zhourui /]# docker pull tomcat
[root@zhourui /]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tomcat 9.0 040bdb29ab37 2 months ago 649MB
tomcat latest 040bdb29ab37 2 months ago 649MB
nginx latest f6d0b4767a6c 2 months ago 133MB
centos latest 300e315adb2f 3 months ago 209MB
hello-world latest bf756fb1ae65 14 months ago 13.3kB
[root@zhourui /]# docker run -d -p 3355:8080 --name tomcat01 tomcat
53197d7745a2d7f83f3a45b1f474a189eb7f496b0cf08c9a509a6c390680e347
[root@zhourui /]# curl localhost:3355
浏览器测试访问:http://39.105.48.232:3355/(阿里云安全组开启端口),可以访问但是显示404。
#进入容器
[root@zhourui /]# docker exec -it tomcat01 /bin/bash
root@53197d7745a2:/usr/local/tomcat# ls
BUILDING.txt CONTRIBUTING.md LICENSE NOTICE README.md RELEASE-NOTES RUNNING.txt bin conf lib logs native-jni-lib temp webapps webapps.dist work
root@53197d7745a2:/usr/local/tomcat# cd webapps
root@53197d7745a2:/usr/local/tomcat/webapps# ls
root@53197d7745a2:/usr/local/tomcat/webapps#
#发现ll无法使用,ls-al可以使用,命令少了。webapps中是空的,默认的是最小的镜像,不必要的被删除了,保证的是最小可用环境。
如果想要访问,可以复制webapps.dist目录的内容到webapps中
root@53197d7745a2:/usr/local/tomcat/webapps# cd ..
root@53197d7745a2:/usr/local/tomcat# cd webapps.dist
root@53197d7745a2:/usr/local/tomcat/webapps.dist# ls
ROOT docs examples host-manager manager
root@53197d7745a2:/usr/local/tomcat/webapps.dist# cd ..
root@53197d7745a2:/usr/local/tomcat# cp -r webapps.dist/* webapps
root@53197d7745a2:/usr/local/tomcat# cd webapps
root@53197d7745a2:/usr/local/tomcat/webapps# ls
ROOT docs examples host-manager manager
root@53197d7745a2:/usr/local/tomcat/webapps#
再次刷新网页访问即可!
#es暴漏的端口十分多
#es十分耗内存
#es的数据一般需要放置到安全目录,挂载。
#--net somenetwork 网络配置
#启动(启动前停掉其它的容器,防止启动不了)
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2
#docker stats 容器id 查看cpu的状态
#启动后 发现执行docker ps命令非常卡,因为内存快耗尽。
启动后可以从宝塔上看到自己服务器的内存状态。(也可以使用命令docker stats 容器id 查看cpu,内存的状态)
停掉es
[root@zhourui /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
94c6cad2a01d elasticsearch:7.6.2 "/usr/local/bin/dock…" 5 minutes ago Up 5 minutes 0.0.0.0:9200->9200/tcp, 0.0.0.0:9300->9300/tcp elasticsearch
[root@zhourui /]# docker stop 94c6cad2a01d
94c6cad2a01d
这时查看服务器的状态
再次启动,增加内存的配置,修改配置文件,-e 环境配置修改。
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
docker run -d -p 9222:9000 \
--restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
启动portainer后访问测试:http://39.105.48.232:9222/,密码可以随意输入。
进入后选择local,点击connect
可以看到镜像,容器等
查看镜像
镜像是什么:镜像是一种轻量级的,可执行的独立软件包。用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码,运行时,库,环境变量和配置文件。
将应用直接打包为docker镜像,就可以直接跑起来。
如何得到镜像:
UnionFS(联合文件系统):Union文件系统(UnionFS)是一种分层,轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同的目录挂载到同一个虚拟文件系统下。Union文件系统是 docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作具体的应用镜像。
特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。
Docker镜像加载原理:docker镜像实际上是由一层一层的文件系统组成,这种层级的文件系统叫UnionFS(联合文件系统)。
bootfs(boot file system)主要包含bootloader和kernel,bootloader主要是引导加载kernel,Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs,这一层与我们典型的Linux/Unix系统是一样的,包含boot加载和内核,当boot加载完之后整个内核都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。
rootfs(root file system)在bootfs之上,包含的就是典型LInux系统中的 /dev,/proc,/bin,/etc等标准目录和文件,rootfs就是各种不同的操作系统发行版,比如Ubantu,Centos等。
可以使用docker images看到Centos的镜像非常小。
对于一个精简的OS,rootfs可以很小,只需包含最基本的命令,工具和程序库就可以了,因为底层直接用Host的kernel,自己只需提供rootfs就可以了,因此可见对于不同的Linux发行版,bootfs基本是一致的,rootfs会有差别,因此不同的发行版可以共用bootfs。
下载一个镜像,观察日志输出,可以看到是一层一层的在下载(分层下载,提高了复用性)
使用docker inspect redis,可以看到RootFS
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:cb42413394c4059335228c137fe884ff3ab8946a014014309676c25e3ac86864",
"sha256:8e14cb7841faede6e42ab797f915c329c22f3b39026f8338c4c75de26e5d4e82",
"sha256:1450b8f0019c829e638ab5c1f3c2674d117517669e41dd2d0409a668e0807e96",
"sha256:f927192cc30cb53065dc266f78ff12dc06651d6eb84088e82be2d98ac47d42a0",
"sha256:a24a292d018421783c491bc72f6601908cb844b17427bac92f0a22f5fd809665",
"sha256:3480f9cdd491225670e9899786128ffe47054b0a5d54c48f6b10623d2f340632"
]
},
理解:所有的Docker镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,都会在当前的镜像层上,创建新的镜像层。在添加额外的镜像层时,镜像始终保持是当前所有镜像的组合。
特点:
docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部。这一层通常是我们所说的容器层,容器之下都是镜像层。
docker commit #提交容器成为一个新的副本
#命令和git类似
docker commit -m=“提交描述信息” -a=“作者” 容器id 目标镜像名:[TAG]
测试
#启动一个tomcat
docker run -it -p 8081:8080 tomcat
#在新的窗口进入tomcat
[root@zhourui /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS 1fd9b7b4cb3d tomcat "catalina.sh run" 28 seconds ago Up 27 seconds 0.0.0.0:8081->8080/tcp
[root@zhourui /]# docker exec -it 1fd9b7b4cb3d /bin/bash
#官方默认的tomcat的webapps下面没有应用,自己拷贝
cp -r webapps.dist/* webapps
#提交自己的镜像,以后使用修改过的镜像即可
[root@zhourui /]# docker commit -a="zhourr" -m="add webapps" 1fd9b7b4cb3d tomcat02:1.0
sha256:1c7804b415ba38099178f63e48444aebec938252632defd16bb35acc71bdabab
[root@zhourui /]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tomcat02 1.0 1c7804b415ba 6 seconds ago 654MB
redis latest 621ceef7494a 2 months ago 104MB
tomcat 9.0 040bdb29ab37 2 months ago 649MB
tomcat latest 040bdb29ab37 2 months ago 649MB
nginx latest f6d0b4767a6c 2 months ago 133MB
centos latest 300e315adb2f 3 months ago 209MB
portainer/portainer latest 62771b0b9b09 8 months ago 79.1MB
elasticsearch 7.6.2 f29a1ee41030 12 months ago 791MB
hello-world latest bf756fb1ae65 14 months ago 13.3kB
[root@zhourui /]#
对容器进行修改后,想保存容器的状态,通过commit来提交,下次就可以使用自己提交的这个镜像了。就好比 vm 的快照功能。
如果数据在容器中,那么将容器删除,数据就会丢失!需求,数据可持久化!!
MySQL容器删除,数据丢失,需求,MySQL数据可以存储在本地!!
容器之间可以有一个数据共享的技术。Docker容器中产生的数据,同步到本地。
这就是卷技术!将容器内的目录,挂载到主机上。
数据持久化和同步操作,容器间也是可以数据共享的。
方式一:使用命令来挂载 -v
docker -it -v主机内的目录:容器内的目录
#测试
[root@zhourui home]# docker run -it -v /home/zrtest:/home centos /bin/bash
#启动后使用 docker inspect 容器id 查看
使用 docker inspect 容器id 查看
测试文件的同步
1.停止容器
2.修改宿主机上的文件
3.启动容器,发现文件依旧是同步的
好处:以后修改只需要在本地修改即可,不需要进入容器!
MySQL的数据持久化问题!
#获取镜像
docker pull mysql:5.7
#运行容器,数据挂载。安装mysql需要配置密码的,注意!
#官方测试连接方法
docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
#启动MySQL
-d:后台运行
-p:端口映射
-v:数据卷挂载
-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
#在本地连接上后创建一个test数据库,查看映射路径是否可以。
在本地使用Navicat测试连接
将容器删除后
[root@zhourui data]# ls
auto.cnf ca.pem client-key.pem ibdata1 ib_logfile1 mysql private_key.pem server-cert.pem sys
ca-key.pem client-cert.pem ib_buffer_pool ib_logfile0 ibtmp1 performance_schema public_key.pem server-key.pem test
可以看到test数据库还在,即挂载到本地的数据卷没有丢失,这就实现了容器数据的持久化。
#匿名挂载
-P(大写P 随机映射端口)
-v 容器内路径
docker run -d -P --name nginx01 -v /etc/nginx nginx
#查看所有的卷的情况
[root@zhourui home]# docker volume ls
DRIVER VOLUME NAME
local 42a60ffb1a9dfcefffdf269e3a08fcb9172a082babe6ea19b864d5f679eb4361
local 93e2f2060025965b83b0433b95e29ac325c25fa8684b79a12617438ffe898941
local 271ccfa1da7814fa8fceb5b482ce86009f97e29c09dca69bcc594a0d8fabb92a
#匿名挂载:这里-v的时候只写了容器内的路径,没有写容器外的路径
#具名挂载
[root@zhourui home]# docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
3024685007a57eda45820c8c07920cea08b84b7847b86fd97f5f71f7100b8fbd
[root@zhourui home]# docker volume ls
DRIVER VOLUME NAME
local 42a60ffb1a9dfcefffdf269e3a08fcb9172a082babe6ea19b864d5f679eb4361
local 93e2f2060025965b83b0433b95e29ac325c25fa8684b79a12617438ffe898941
local 271ccfa1da7814fa8fceb5b482ce86009f97e29c09dca69bcc594a0d8fabb92a
local juming-nginx
[root@zhourui home]#
#通过-v 卷名:容器内名字
#查看卷
[root@zhourui home]# docker volume inspect juming-nginx
所有docker容器内的卷,在没有指定目录的情况下都是在 /var/lib/docker/volumes/xxxx/_data。
通过具名挂载可以方便的找到我们的卷,大多数情况下都是使用具名挂载。
#如何确定是具名挂载还是匿名挂载,还是指定路径挂载
-v 容器内路径 #匿名挂载
-v 卷名:容器内路径 #具名挂载
-v /宿主机路径:容器内路径 #指定路径挂载
拓展:
#通过-v 卷名:容器内路径:ro或rw 改变读写权限
ro readonly #只读
rw readwrite #可读可写
#一旦设置了容器权限,容器对挂载出来的文件就有限定了
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:ro nginx
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:rw nginx
#只要看到ro,就说明这个文件只能通过宿主机来操作,容器内部是无法操作的!
Dockerfile就是用来构建 docker 镜像的构建文件!命令脚本!
通过这个脚本可以生成镜像。镜像是一层一层的,脚本是一个个的命令,每个命令都是一层。
方式二:
[root@zhourui home]# pwd
/home
[root@zhourui home]# cd docker-test-volume/
[root@zhourui docker-test-volume]# pwd
/home/docker-test-volume
[root@zhourui docker-test-volume]# vim dockerfile #创建dockerfile
[root@zhourui docker-test-volume]# cat dockerfile #文件中添加以下内容后查看(文件中内容 指令(大写) 参数)
#每个命令就是镜像的一层
FROM centos
VOLUME ["volume01","volume02"] #匿名挂载
CMD echo "....end...."
CMD /bin/bash
[root@zhourui docker-test-volume]# docker build -f /home/docker-test-volume/dockerfile -t zhour/centos:1.0 .
#启动自己生成的容器
docker run -it 29e054de9dd4 /bin/bash
#在volume01中创建文件
[root@e224b7ebc0d7 volume01]# ls
[root@e224b7ebc0d7 volume01]# touch container.txt
[root@e224b7ebc0d7 volume01]# ls
container.txt
[root@e224b7ebc0d7 volume01]#
查看匿名卷挂载的路径:docker inspect 容器id
进入挂载的路径中查看
[root@zhourui /]# cd /var/lib/docker/volumes/f517ef934bb1d4376751cf0ec11608ed0fd287844436ba62cad973ce0f67dee8/_data
[root@zhourui _data]# ls
container.txt
[root@zhourui _data]#
可以看到文件已经同步!!
这种方式较常使用,通常用于构建自己的镜像。
假设构建镜像时没有挂载卷,需要手动挂载,-v 卷名:容器内路径。
启动三个容器
#创建docker01
[root@zhourui /]# docker run -it --name docker01 29e054de9dd4
[root@255f9d13bea7 /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var volume01 volume02
#创建docker02
[root@zhourui /]# docker run -it --name docker02 --volumes-from docker01 29e054de9dd4
[root@861b5d25a8ca /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var volume01 volume02
#在docker01的volume01中创建文件
[root@zhourui /]# docker attach 255f9d13bea7
[root@255f9d13bea7 /]# cd volume01
[root@255f9d13bea7 volume01]# ls
[root@255f9d13bea7 volume01]# touch docker01
#进入docker02的volume01中查看
[root@861b5d25a8ca /]# cd volume01
[root@861b5d25a8ca volume01]# ls
docker01
#创建docker03并在volume01中增加docker03文件
[root@zhourui /]# docker run -it --name docker03 --volumes-from docker01 29e054de9dd4
[root@7a405584084a /]# cd volume01
[root@7a405584084a volume01]# ls
docker01
[root@7a405584084a volume01]# touch docker03
[root@7a405584084a volume01]# ls
docker01 docker03
#在docker01中查看volume01
[root@255f9d13bea7 volume01]# ls
docker01 docker03
[root@255f9d13bea7 volume01]#
通过 --volumes-from 可以实现容器间的数据共享!!
可以测试删除掉 docker01 ,再去查看 docker02 和 docker03 ,数据仍然还在。
三个容器之间的文件是相互拷贝的,删掉一个不会丢失数据。
应用:多个 MySQL 或者 Redis 之间实现数据共享!!
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
docker run -d -p 3310:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01 mysql:5.7
#可以实现两个MySQL之间的数据同步
结论:容器之间配置信息的传递,数据卷容器的生命周期是一直持续到没有容器使用为止。
通过 -v 将数据持久化到本地,本地的数据是不会删除的。
dockerfile是用来构建 docker 镜像的文件。命令参数脚本。
构建步骤:
查看官方 centos,点击版本会跳转至 GitHUb
很多的官方镜像都是基础包,一些功能没有,我们就需要自己搭建。
基础知识:
docker 是面向开发的,发布项目做镜像,就需要编写 dockerfile 文件。
Docker镜像逐渐成为企业交付的标准。
dockerfile :构建文件,定义了一切所需的环境和源代码。
dockerImage:通过 dockerfile 构建生成的镜像,最终发布和运行的产品。
docker 容器:容器是镜像运行起来后提供服务的。
FROM #基础镜像,一切从这里开始构建
MAINTAINER #镜像是谁写的
RUN #docker 镜像构建的时候需要运行的命令
ADD #步骤:使用tomcat镜像,tomcat压缩包,就是添加的内容
WORKDIR #镜像的工作目录
VOLUME #挂载的目录位置
EXPOSE #暴漏端口配置
CMD #指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT #指定这个容器启动的时候要运行的命令,可以追加命令
ONBUILD #当构建一个被继承的 dockerfile 这个时候会运行 ONBUILD 的指令,触发指令
COPY #类似add命令,将文件拷贝拷贝到目录中
ENV #构建的时候设置环境变量
Docker Hub 中99%的镜像都是由这个基础镜像 FROM scratch 来配置构建的
FROM scratch
ADD centos-8-x86_64.tar.xz /
LABEL \
org.label-schema.schema-version="1.0" \
org.label-schema.name="CentOS Base Image" \
org.label-schema.vendor="CentOS" \
org.label-schema.license="GPLv2" \
org.label-schema.build-date="20201204"
CMD ["/bin/bash"]
创建一个自己的 CentOS
#编写 dockerfile 的文件
[root@zhourui home]# cd dockerfile/
[root@zhourui dockerfile]# ls
[root@zhourui dockerfile]# vim mydockerfile-centos
[root@zhourui dockerfile]# cat mydockerfile-centos
FROM centos
MAINTAINER zhourr<[email protected]>
ENV MYPATH /usr/local
WORKDIR $MYPATH #进去后的工作目录,进去后 pwd 查看
RUN yum -y install vim #安装 vim
RUN yum -y install net-tools #安装后可以使用 ifconfig (不安装只能用 ip add)
EXPOSE 80
CMD echo $MYPATH
CMD echo "...end..."
CMD /bin/bash
#通过这个文件构建镜像
-f 构建文件路径
-t 镜像名:[tag]
最后有个 .
[root@zhourui dockerfile]# docker build -f mydockerfile-centos -t mycentos:0.1 .
...
Successfully built ddba7ccc7eee
Successfully tagged mycentos:0.1
#测试运行
docker run -it mycentos:0.1
默认的 centos 以下命令无法使用
[root@95c725dda358 /]# pwd
/
[root@95c725dda358 /]# vim
bash: vim: command not found
[root@95c725dda358 /]# ifconfig
bash: ifconfig: command not found
[root@95c725dda358 /]#
测试运行自己创建的镜像这些命令就可以使用了。
我们可以列出本地镜像的变更历史 docker history 镜像id
CMD和ENTRYPOINT的区别
CMD #指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT #指定这个容器启动的时候要运行的命令,可以追加命令
测试 CMD
[root@zhourui dockerfile]# vim dockerfile-cmd-test
FROM centos
CMD ["ls","-a"]
#构建镜像
[root@zhourui dockerfile]# docker build -f dockerfile-cmd-test -t cmdtest .
....
Successfully built a44c7103184f
Successfully tagged cmdtest:latest
# run 运行,可以看到 ls-a 命令生效
[root@zhourui dockerfile]# docker run a44c7103184f
.
..
.dockerenv
bin
dev
etc
home
lib
...
#追加一个 l ,希望返回 ls-al
[root@zhourui dockerfile]# docker run a44c7103184f -l
docker: Error response from daemon: OCI runtime create failed: container_linux.go:367: starting container process caused: exec: "-l": executable file not found in $PATH: unknown.
#此时报错,因为使用CMD,-l替换了["ls","-a"],-l不是命令,所以报错
#需要使用以下完整命令
[root@zhourui dockerfile]# docker run a44c7103184f ls -al
测试 ENTRYPOINT
[root@zhourui dockerfile]# vim dockerfile-entrypoint
FROM centos
ENTRYPOINT ["ls","-a"]
[root@zhourui dockerfile]# docker build -f dockerfile-entrypoint -t entrypointtest .
...
Successfully built 34773b8b0398
Successfully tagged entrypointtest:latest
[root@zhourui dockerfile]# docker run 34773b8b0398
.
..
.dockerenv
bin
dev
etc
home
lib
...
# 添加 -l,是可以直接追加到后面的,ls -a -l
[root@zhourui dockerfile]# docker run 34773b8b0398 -l
total 0
drwxr-xr-x 1 root root 6 Mar 27 14:51 .
drwxr-xr-x 1 root root 6 Mar 27 14:51 ..
-rwxr-xr-x 1 root root 0 Mar 27 14:51 .dockerenv
lrwxrwxrwx 1 root root 7 Nov 3 15:22 bin -> usr/bin
drwxr-xr-x 5 root root 340 Mar 27 14:51 dev
drwxr-xr-x 1 root root 66 Mar 27 14:51 etc
drwxr-xr-x 2 root root 6 Nov 3 15:22 home
lrwxrwxrwx 1 root root 7 Nov 3 15:22 lib -> usr/lib
Docker中很多命令都十分相似,需要去对比测试一下,才能发现其中的区别。
编写 Dockerfile 文件,官方命名:Dockerfile,build的时候会自动寻找这个文件,就不需要 -f 指定了。(在home/zhour-tar目录下,vim Dockerfile),压缩包会自动解压。
FROM centos
MAINTAINER zhourr<[email protected]>
COPY readme.txt /usr/local/read.txt
ADD jdk-8u281-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-9.0.44.tar.gz /usr/local/
RUN yum -y install vim
ENV MYPATH /usr/local
WORKDIR $MYPATH
ENV JAVA_HOME /usr/local/jdk1.8.0_281
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.44
ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.44
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
EXPOSE 8080
CMD /usr/local/apache-tomcat-9.0.44/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.44/bin/logs/catalina.out
构建镜像
[root@zhourui zhour-tar]# ls
apache-tomcat-9.0.44.tar.gz Dockerfile jdk-8u281-linux-x64.tar.gz readme.txt
#构建
[root@zhourui zhour-tar]# docker build -t diytomcat .
启动镜像
[root@zhourui zhour-tar]# docker run -d -p 3030:8080 --name zhoutomcat -v /home/zhour-tar/test:/usr/local/apache-tomcat-9.0.44/webapps/test -v /home/zhour-tar/tomcatlogs/:/usr/local/apache-tomcat-9.0.44/logs diytomcat
访问测试
发布项目(配置了数据卷挂载,直接在容器外编写项目就可以发布了)在test中新建
web.xml
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
Hello zhourrr!!
Hello World!
<%
System.out.println("----my tomcat test----");
%>
访问http://39.105.48.232:3030/test/
需要掌握 Dockersfile 的编写!!
在 Docker Hub 上注册账号,在服务器登录后就可以提交自己的镜像了。
[root@zhourui tomcatlogs]# docker login --help
Usage: docker login [OPTIONS] [SERVER]
Log in to a Docker registry.
If no server is specified, the default is defined by the daemon.
Options:
-p, --password string Password
--password-stdin Take the password from stdin
-u, --username string Username
登录
[root@zhourui tomcatlogs]# docker login -u zhourui88
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
提交
[root@zhourui tomcatlogs]# docker push diytomcat
Using default tag: latest
The push refers to repository [docker.io/library/diytomcat]
e21bfbb06ee5: Preparing
145f6d70801c: Preparing
f3ba2f2219d6: Preparing
f83a7c49f1e3: Preparing
2653d992f4ef: Preparing
denied: requested access to the resource is denied #拒绝
#需要增加一个tag
[root@zhourui tomcatlogs]# docker tag ea84d80641b1 zhourui88/tomcat:1.0
#查看
[root@zhourui tomcatlogs]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
diytomcat latest ea84d80641b1 About an hour ago 640MB
zhourui88/tomcat 1.0 ea84d80641b1 About an hour ago 640MB
#提交
[root@zhourui tomcatlogs]# docker push zhourui88/tomcat:1.0
提交的时候镜像也是按层级来提交的!
阿里云服务器
登录阿里云
找到容器镜像服务
创建命名空间
#登录
[root@zhourui /]# sudo docker login --username=周锐822 registry.cn-beijing.aliyuncs.com
#提交到阿里云,这里没有更改tag,显示上传成功,但是我没有找到镜像
[root@zhourui /]# docker push zhourui88/tomcat:1.0
The push refers to repository [docker.io/zhourui88/tomcat]
e21bfbb06ee5: Layer already exists
145f6d70801c: Layer already exists
f3ba2f2219d6: Pushing [==========> ] 77.66MB/356.6MB
f83a7c49f1e3: Layer already exists
#上传阿里云
[root@zhourui /]# sudo docker tag ea84d80641b1 registry.cn-beijing.aliyuncs.com/docker-zhourui/zhourui-test:1.0
[root@zhourui /]# docker images
REPOSITORY TAG IMAGE ID CREATED
diytomcat latest ea84d80641b1 3 hours ago
zhourui88/tomcat 1.0 ea84d80641b1 3 hours ago
registry.cn-beijing.aliyuncs.com/docker-zhourui/zhourui-test 1.0 ea84d80641b1 3 hours ago
[root@zhourui /]# docker push registry.cn-beijing.aliyuncs.com/docker-zhourui/zhourui-test:1.0
上传后查看
ip addr
#启动容器
[root@zhourui /]# docker run -d -P --name tomcat01 tomcat
72dee6c91e3f593c69858191014b9d228c6494b0aa049cd1f620350c1c46cd56
#查看容器内部网络地址 eth0@if123 ip地址 docker分配的
[root@zhourui /]# docker exec -it tomcat01 ip addr
1: lo: 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
122: eth0@if123: 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@zhourui /]# 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.062 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.045 ms
原理:我们每启动一个 docker 容器,docker就会给docker容器分配一个ip,我们只要安装了docker,就会有一个网卡docker0.
桥接模式,使用的技术是 evth-pair 技术
这时再输入 ip addr,发现多了一个网卡
再启动一个 tomcat02 发现又多了一个网卡 (docker run -d -P --name tomcat02 tomcat) ipaddr
查看tomcat02 ip addr
[root@zhourui /]# docker exec -it tomcat02 ip addr
1: lo: 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
124: eth0@if125: mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
可以发现容器的网卡都是一对一对的,【122: eth0@if123】【124: eth0@if125】。
evth-pair:就是一对虚拟设备接口,它们都是成对出现的,一段连着协议,一段彼此相连。
所以,evth-pair就充当一个桥梁,连接各种虚拟网络设备。
测试tomcat01和tomcat02之间能不能ping通:
[root@zhourui /]# docker exec -it tomcat02 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.091 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.069 ms
#可以看到,容器之间是可以通信的
流程图理解
tomcat01 和 tomcat02 是公用一个路由器 docker0 。
所有容器不指定网络的情况下,都是 docker0 路由的,doker会给容器分配一个默认的可用 ip。
Docker使用的是 Linux 的桥接,宿主机中是 Docker 容器的网桥(Docker0)
Docker 中所有的网络接口都是虚拟的,虚拟的转发效率高。
只要删除容器,对应的网桥就没了。
docker network ls,docker network inspect (桥接network id)可以查看
假设我们想通过容器的名字来ping,而不是通过ip,就需要使用 --link。
[root@zhourui /]# docker exec -it tomcat02 ping tomcat01
ping: tomcat01: Name or service not known
#通过--link可以解决
[root@zhourui /]# docker run -d -P --name tomcat03 --link tomcat02 tomcat
131bbb6e180687ff284ef2cabc78f4104dfc5d1018ee1e2f11a5b6e192bdc8bb
[root@zhourui /]# 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.101 ms
#反向ping
[root@zhourui /]# docker exec -it tomcat02 ping tomcat03
ping: tomcat03: Name or service not known
docker network ls,docker network inspect (桥接network id)可以查看
–link 使用后,tomcat03在本地配置了tomcat02
[root@zhourui /]# 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 1fff64acaf04
172.17.0.4 131bbb6e1806
本质:在hosts的配置中增加了 tomcat02 的映射。
真实开发中,已经不建议使用 --link 了。
自定义网络,不使用 docker0。docker0不支持容器名连接访问。
查看所有的docker网络
[root@zhourui /]# docker network ls
NETWORK ID NAME DRIVER SCOPE
25000c3be4a4 bridge bridge local #桥接
b518cb3beba9 host host local
bcd06ce03d47 none null local
网络模式
bridge:桥接(docker默认)自己创建也使用 bridge 模式
none:不配置网络
host:和宿主机共享网络
container:容器内网络联通(局限性很大)
测试:
#直接启动,默认是 --net bridge 的,
docker run -d -P --name tomcat01 tomcat
docker run -d -P --name tomcat01 --net bridge tomcat
#docker0特点,默认,域名不能访问,--link可以打通连接
#自定义网络
# --driver bridge
# --subnet 192.168.0.0/16
# --gateway 192.168.0.1
[root@zhourui /]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
6219f386e2bfc7f837554de2b011ec1d649d6eaafa617fcf4bdd2d8091cf82b2
[root@zhourui /]# docker network ls
NETWORK ID NAME DRIVER SCOPE
25000c3be4a4 bridge bridge local
b518cb3beba9 host host local
6219f386e2bf mynet bridge local
bcd06ce03d47 none null local
查看自己的网络:docker network inspect mynet
创建两个容器,连上自己的网络
[root@zhourui /]# docker run -d -P --name tomcat-net-01 --net mynet tomcat
c638c0cee8dff978e60532b9a1ddac74f10a45bfb6b542bf3fd3079f69ec5515
[root@zhourui /]# docker run -d -P --name tomcat-net-02 --net mynet tomcat
e9aee8d922b19af82f02e9e50b28a301ab10e7eb57828c454cb57b9ac5bdc0ae
[root@zhourui /]# docker network inspect mynet
[
{
"Name": "mynet",
"Id": "6219f386e2bfc7f837554de2b011ec1d649d6eaafa617fcf4bdd2d8091cf82b2",
"Created": "2021-03-28T17:29:39.571024726+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": {
"c638c0cee8dff978e60532b9a1ddac74f10a45bfb6b542bf3fd3079f69ec5515": {
"Name": "tomcat-net-01",
"EndpointID": "6d4ac08b616e2e33e8fb7a3e8659b5a6ff2e381083572dbe202f7b8598347177",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/16",
"IPv6Address": ""
},
"e9aee8d922b19af82f02e9e50b28a301ab10e7eb57828c454cb57b9ac5bdc0ae": {
"Name": "tomcat-net-02",
"EndpointID": "187733df51f17912e402211643ce7136cbb725d85a0c1045ef7e903471d9f878",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
#再次测试 ping 连接
[root@zhourui /]# docker exec -it tomcat-net-01 ping 192.168.0.3
PING 192.168.0.3 (192.168.0.3) 56(84) bytes of data.
64 bytes from 192.168.0.3: icmp_seq=1 ttl=64 time=0.115 ms
64 bytes from 192.168.0.3: icmp_seq=2 ttl=64 time=0.067 ms
64 bytes from 192.168.0.3: icmp_seq=3 ttl=64 time=0.068 ms
^C
--- 192.168.0.3 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 67ms
rtt min/avg/max/mdev = 0.067/0.083/0.115/0.023 ms
#不使用 --link。也可以ping名字了
[root@zhourui /]# 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.075 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.070 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=3 ttl=64 time=0.086 ms
自定义的网络donker帮我们维护好了关系,推荐使用自定义的网络。
应用:
redis:不同的集群使用不同的网络,保证集群是安全和健康的(192.168.xxx.xxx)
mysql:不同的集群使用不同的网络,保证集群是安全和健康的(192.182.xxx.xxx)
创建两个容器在默认的docker0网络下
[root@zhourui /]# docker run -d -P --name tomcat01 tomcat
[root@zhourui /]# docker run -d -P --name tomcat02 tomcat
现在就有以下的四个容器在在 docker0 和 mynet 网络下。怎样去打通 tomcat01 连接到 mynet。
通过 --help 查看命令
测试打通 tomcat01 连接到 mynet
[root@zhourui /]# docker network connect mynet tomcat01
[root@zhourui /]# docker network inspect mynet
#打通之后,tomcat01被放到了 mynet 网络下,
#一个容器两个 ip 地址
测试
[root@zhourui /]# 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.092 ms
#反向也是可以ping通的
[root@zhourui /]# docker exec -it tomcat-net-01 ping tomcat01
PING tomcat01 (192.168.0.4) 56(84) bytes of data.
64 bytes from tomcat01.mynet (192.168.0.4): icmp_seq=1 ttl=64 time=0.118 ms
#tomcat02 是没有连接上 mynet 的
[root@zhourui /]# docker exec -it tomcat02 ping tomcat-net-01
ping: tomcat-net-01: Name or service not known
结论:如果需要跨网络操作,就需要使用 docker network connect 网络 容器名称 来联通!!
#创建redis的网络
docker network create redis --subnet 172.38.0.0/16
#通过脚本创建6个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
docker run -p 637${port}:6379 -p 1637${port}:16379 --name redis-${port} \
-v /mydata/redis/node-${port}/data:/data \
-v /mydata/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.1${port} redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf; \
#=====================================================================
#单个启动
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
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
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
#创建集群
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
[root@zhourui /]# 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
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 172.38.0.15:6379 to 172.38.0.11:6379
Adding replica 172.38.0.16:6379 to 172.38.0.12:6379
Adding replica 172.38.0.14:6379 to 172.38.0.13:6379
M: 1524f57c751c662847b24edb3cf4433e42e11dae 172.38.0.11:6379
slots:[0-5460] (5461 slots) master
M: 3d0a68b584e5935b6174d8b8e0603a14eb246393 172.38.0.12:6379
slots:[5461-10922] (5462 slots) master
M: cce404917b84b790cf39ac1f6dff85c1c080c9a1 172.38.0.13:6379
slots:[10923-16383] (5461 slots) master
S: 2fb9e53fde60fb288e87a8bccf37f2d521c5f5be 172.38.0.14:6379
replicates cce404917b84b790cf39ac1f6dff85c1c080c9a1
S: d977bb4c2b2a45bbbeb74cc123bd87dba1acd257 172.38.0.15:6379
replicates 1524f57c751c662847b24edb3cf4433e42e11dae
S: 317ccf18aefe00a7a45820b6509bd8c9fc1f7097 172.38.0.16:6379
replicates 3d0a68b584e5935b6174d8b8e0603a14eb246393
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
..
>>> Performing Cluster Check (using node 172.38.0.11:6379)
M: 1524f57c751c662847b24edb3cf4433e42e11dae 172.38.0.11:6379
slots:[0-5460] (5461 slots) master
1 additional replica(s)
M: cce404917b84b790cf39ac1f6dff85c1c080c9a1 172.38.0.13:6379
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
M: 3d0a68b584e5935b6174d8b8e0603a14eb246393 172.38.0.12:6379
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
S: 317ccf18aefe00a7a45820b6509bd8c9fc1f7097 172.38.0.16:6379
slots: (0 slots) slave
replicates 3d0a68b584e5935b6174d8b8e0603a14eb246393
S: d977bb4c2b2a45bbbeb74cc123bd87dba1acd257 172.38.0.15:6379
slots: (0 slots) slave
replicates 1524f57c751c662847b24edb3cf4433e42e11dae
S: 2fb9e53fde60fb288e87a8bccf37f2d521c5f5be 172.38.0.14:6379
slots: (0 slots) slave
replicates cce404917b84b790cf39ac1f6dff85c1c080c9a1
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
/data # redis-cli -c
127.0.0.1:6379> cluster info
127.0.0.1:6379> cluster nodes
127.0.0.1:6379> set a b
-> Redirected to slot [15495] located at 172.38.0.13:6379
OK
172.38.0.13:6379>
#新建窗口 docker stop redis-3
#获取 a 的值
127.0.0.1:6379> get a
-> Redirected to slot [15495] located at 172.38.0.14:6379
"b"
搭建redis集群完成!!
构建一个SpringBoot项目
@RestController
public class HelloController {
@RequestMapping("/hello")
public String hello(){
return "Hello zhour!";
}
}
打包应用,package
编写dockerfile
FROM java:8
COPY *.jar /app.jar
CMD ["---server port 8080---"]
EXPOSE 8080
ENTRYPOINT ["java","-jar","app.jar"]
构建镜像(使用 ftp 将文件上传至服务器)
[root@zhourui idea]# ls
demo-docker-0.0.1-SNAPSHOT.jar Dockerfile
[root@zhourui idea]# docker build -t boottestzr .
发布运行
[root@zhourui idea]# docker run -d -P --name ideaboot-web boottestzr
访问
如需浏览器访问,阿里云开发端口,或者运行时 -p 暴漏已开放的端口即可!!