帮助命令
docker version 显示版本信息
docker info 显示系统信息,包括镜像和容器的数量
docker 命令 --help
systemctl restart docker.service 重启docker
镜像命令
docker images 查看所有本地的主机上的镜像
docker search 搜索镜像
容器命令
新建容器并启动:docker run [可选参数] images
调试,启动并进入容器:docker run -it centos /bin/bash
docker其他命令
docker ps 命令
-a #列出正在运行的容器+带出历史运行过的容器
-n=? #显示最近创建过的容器
-q #只显示容器的编号
退出容器
exit #直接容器停止并退出
Ctrl+P+Q #容器不停止但退出
删除容器
docker rm 容器id #删除指定容器,不能删除正在运行的容器
docker rm -f $(docker ps -aq) #删除所有容器
docker ps -a -q|xargs docker rm #删除所有容器
查看日志
docker logs -f -t --tail 容器
自己编写一段shell脚本
[root@linuxprobe ~]# docker run -d centos /bin/sh -c 'while true;do echo wsnd;sleep 1;done'
[root@linuxprobe ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
834f5c4d5db7 centos "/bin/sh -c 'while t…" 2 seconds ago Up 2 seconds angry_austin
显示日志
-tf #显示日志
--tail number #要显示日志条数
[root@linuxprobe ~]# docker logs -f -t --tail 10 834f5c4d5db7
查看容器中进程信息
命令 docker top 容器id
[root@linuxprobe ~]# docker top 834f5c4d5db7
UID PID PPID C STIME TTY TIME CMD
root 22144 22125 0 15:30 ? 00:00:00 /bin/sh -c while true;do echo wsnd;sleep 1;done
root 22763 22144 0 15:40 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1
查看镜像的元数据
命令
docker inspect 容器id
进入当前正在运行的容器
通常容器使用后台方式运行,需要进入容器,修改一些配置
命令
docker exec -it 容器id /bin/bash
测试
[root@linuxprobe ~]# docker exec -it 834f5c4d5db7 /bin/bash
[root@834f5c4d5db7 /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
[root@834f5c4d5db7 /]# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 07:30 ? 00:00:00 /bin/sh -c while true;do echo wsnd;sleep 1;done
root 1058 0 0 07:48 pts/0 00:00:00 /bin/bash
root 1088 1 0 07:48 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1
root 1089 1058 0 07:48 pts/0 00:00:00 ps -ef
方法二
docker attach 容器id
测试
[root@834f5c4d5db7 /]# docker attach 834f5c4d5db7
正在执行当前的代码...
docker exec 进入容器后开启一个新的终端,可以在里面操作(常用)
docker attach 进入容器正在执行的终端,不会启动新的连接
从容器拷贝文件到主机上
docker cp 容器id:容器内路径 目的的主机路径
查看当前主机目录下
[root@linuxprobe home]# ls
linux linuxprobe workdir
[root@linuxprobe home]# touch wsnd.java
[root@linuxprobe home]# ls
linux linuxprobe workdir wsnd.java
[root@linuxprobe home]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
484ac31e25ea centos "/bin/bash" 2 minutes ago Up 2 minutes friendly_engelbart
进入docker容器内部
[root@linuxprobe home]# docker attach 484ac31e25ea
[root@484ac31e25ea /]# cd /home/
[root@484ac31e25ea home]# ls
在容器内新建一个文件
[root@484ac31e25ea home]# touch test.java
[root@484ac31e25ea home]# exit
exit
[root@linuxprobe home]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@linuxprobe home]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
484ac31e25ea centos "/bin/bash" 3 minutes ago Exited (0) 13 seconds ago friendly_engelbart
将该文件拷贝出来到主机上
[root@linuxprobe home]# docker cp 484ac31e25ea:/home/test.java /home
[root@linuxprobe home]# ls
linux linuxprobe test.java workdir wsnd.java
拷贝是一个手动过程,未来使用-v卷的技术,可以实现
作业练习
Docker安装Nginx
1、搜索镜像 search 建议去docker hub上搜索,可以看到帮助文档信息
2、下载镜像 pull
3、运行测试
[root@linuxprobe ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 605c77e624dd 7 weeks ago 141MB
mysql 5.7 c20987f18b13 2 months ago 448MB
mysql latest 3218b38490ce 2 months ago 516MB
hello-world latest feb5d9fea6a5 5 months ago 13.3kB
centos latest 5d0da3dc9764 5 months ago 231MB
-d 后台运行
--name 给容器命名
-p 宿主机端口,容器内部端口
[root@linuxprobe ~]# docker run -d --name nginx01 -p 3344:80 nginx
ec6edcb08308222e76b67558602e9d77c5b36e46c11addaf75d8d459a971468e
[root@linuxprobe ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ec6edcb08308 nginx "/docker-entrypoint.…" 5 seconds ago Up 4 seconds 0.0.0.0:3344->80/tcp, :::3344->80/tcp nginx01
[root@linuxprobe ~]# curl localhost:3344
端口暴露的概念
思考:每次改动 nginx配置文件都需要进入容器内部?十分麻烦,要是可以在容器外部提供一个映射路径,达到在容器修改文件名,容器内部就可以自动修改? -v 数据卷!
作业:docker来装一个Tomcat
官方的使用
docker run -it --rm tomcat:9.0
我们之前的启动都是后台,停止了容器之后,容器还是可以查到
docker run -it --rm ,一般用完即删
下载在启动
docker pull tomcat
启动运行
docker run -d -p 3355:8080 --name tomcat01 tomcat
测试访问没有问题
[root@linuxprobe ~]# docker run -d -p 3355:8080 --name tomcat01 tomcat
a5f6c59194b6de8f14a25f2e18779a3218eb0c1f1da2eeddf40b538dbeea2424
进入容器
[root@linuxprobe ~]# docker exec -it tomcat01 /bin/bash
发现问题:1、linux命令少了。 2、没有webapps,阿里云镜像的原因,默认是最小的镜像,所有不必要的都剔除掉。
保证最小可运行的环境
思考:以后部署项目,每次进入容器十分麻烦?要是可以在容器外部提供一个映射路径,webapps,在外部放置项目,就自动同步到内部就好了!
部署es+kibana
es 暴露的端口很多
es 十分耗内存
es 的数据一般需要放置到安全目录!挂载
--net somenetwork ? 网络配置
启动elasticsearch
$ docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2
启动了linux就小卡 docker stats 查看cpu的状态
es是十分耗内存的,1.xG 1核2G!
查看 docker stats
测试一下es是否成功
[root@linuxprobe ~]# curl localhost:9200
{
"name" : "4fa5278395e5",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "zVNHDHddSWWEB7kavXWMng",
"version" : {
"number" : "7.6.2",
"build_flavor" : "default",
"build_type" : "docker",
"build_hash" : "ef48eb35cf30adf4db14086e8aabd07ef6fb113f",
"build_date" : "2020-03-26T06:34:37.794943Z",
"build_snapshot" : false,
"lucene_version" : "8.4.0",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
},
"tagline" : "You Know, for Search"
}
赶紧关闭,增加内存的限制,修改配置文件 -e 环境配置修改
docker run -d --name elasticsearch02 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms512m" elasticsearch:7.6.2
查看 docker stats
使用kibana连接es ? 思考网络如何才能连接过去?
可视化
portainer(先用这个)
docker run -d -p 8088:9000 \--restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
Rancher(CI/CD再用)
什么是portainer ?
Docker图形化界面管理工具!提供一个后台面板供我们操作!
docker run -d -p 8088:9000 \--restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
访问测试:http://ip:8088/
通过它来访问了:
选择本地的local选项
进入之后的面板:
平时不用,测试玩玩
commit镜像
docker commit 提交容器成为一个新的副本
# 命令和git原理类似
docker tomcat -m="提交的描述信息" -a=“作者” 容器id 目标镜像名,[TAG]
实战测试
# 1、启动一个默认的tomcat
# 2、发现这个默认的tomcat是没有webapps应用,镜像的原因,官方的镜像默认webapps下面是没有文件的!
# 3、我自己拷贝进去了基本的文件
# 4、将我们操作过的容器通过commit提交为一个镜像!前面以后就用我们修改过的镜像即可。这就是我们自己的一个修改的镜像
如果想要保存当前容器的状态,就可以通过commit来提交,获得一个镜像,好比VM快照!
到了这里才算是入门Docker
容器数据卷
什么是容器数据卷
docker理念:将应用和环境打包成一个镜像
数据?如果数据都在容器中,那么容器删除,数据就会丢失!需求:数据可以持久化!
MySQL,容器删了,删库跑路!需求:MySQL数据可以存储在本地!
容器之间可以有一个数据共享的技术!Docker容器中产生的数据,同步到本地!
这就是卷技术!目录的挂载,将我们容器内的目录,挂载到Linux上面!
总结:容器的持久化和同步操作!容器间也是可以数据共享的!
使用数据卷
方式一:直接使用命令来挂载 -v
docker run -it -v -p 主机端口,容器内目录
# 测试
[root@linuxprobe home]# docker run -it -v /home/ceshi:/home centos /bin/bash
# 启动起来之后可以通过 docker inspect 容器id
测试文件的同步
再来测试!
- 停止容器
- 宿主机上修改文件
- 启动容器
- 容器内的数据依旧是同步的
好处:以后修改只需要在本地修改即可,容器内会自动同步!
实战:安装MySQL
思考:MySQL的数据持久化问题
# 获取镜像
[root@linuxprobe home]# docker pull mysql:5.7
# 运行容器,需要做数据挂载!
# 安装启动mysql,需要配置密码!
# 官方测试:docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
# 启动我们的
-d 后台运行
-p 端口映射
-v 卷挂载
-e 环境配置
--name 容器
[root@linuxprobe home]# 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
# 启动成功之后,我们在本地使用sqlyog来连接测试一下
# sqlyog 连接到服务器的3310 ---- 3310 和容器内的3306映射,这个时候就可以连接上了!
# 在本地测试创建一个数据库,查看一下我们映射的路径是否ok!
假设我们将容器删除,发现我们挂载到本地的数据卷依旧没有丢失,这就实现了容器数据持久化功能!
具名和匿名挂载
# 匿名挂载
-v 容器内路径
docker run -d -P --name nginx01 -v /ect/nginx nginx
# 查看所有的 volume 的情况
[root@linuxprobe home]# docker volume ls
local 72a2ba8626cb0705e6c800598953d43461ed67388168c56b6653841815d10b61
# 这里发现,这种就是匿名挂载,我们在 -v 只写了容器内的路径,没有写容器外的路径!
#具名挂载
[root@linuxprobe home]# docker run -d -P --name nginx002 -v juming-nginx:/etc/nginx nginx
ad7f44d82a1247a67ade0bcffa4e01683610e7a25b3e06eca15521bf9ec3cf4c
[root@linuxprobe home]# docker volume ls
DRIVER VOLUME NAME
local 72a2ba8626cb0705e6c800598953d43461ed67388168c56b6653841815d10b61
local a2d6dececd85969a5affc6d53632dd660bc771c7ebef4c46c6a9141094c83b54
local juming-nginx
# 通过 -v 卷名:容器内路径
# 查看一下这个卷
所有的docker容器内的卷,没有指定目录的情况下都是在 /var/lib/docker/volumes/xxxx../data
通过具名挂载可以方便找到我们的每一个卷,大多数情况使用具名挂载!
# 如何确定是具名挂载还是匿名挂载,还是指定路径挂载!
-v 容器内路径 # 匿名挂载
-v 卷名:容器内路径 #具名挂载
-v /宿主机路径::容器内路径 #指定路径挂载
拓展:
# 通过 -v 容器内路径:ro rw 改变读写权限
ro readonly # 只读
rw readwrite # 可读可写
# 一旦设置了容器权限,容器对我们挂载啊出来的内容就有限定了!
[root@linuxprobe _data]# docker run -d -P --name nginx002 -v juming-nginx:/etc/nginx:ro nginx
[root@linuxprobe _data]# docker run -d -P --name nginx002 -v juming-nginx:/etc/nginx:rw nginx
# ro 只要看到ro就说明这个路径只能通过宿主机来操作,容器内部是无法操作的!
初识DockerFile
Dockerfile就是用来构建docker镜像的构建文件!命令脚本!先体验一下!
通过这个脚本可以生成镜像,镜像是一层一层的,脚本是一个一个的命令,每个命令都是一层!
# 创建一个dockerfile文件,名字可以随随机 建议dockerfile
# 文件中的内容 指令(大写) 参数
FROM centos
VOLUME ["volume01","volume02"]
CMD echo "-----end-----"
CMD /bin/bash
# 这里的每个命令,就是镜像的一层
# 启动自己写的容器
这个卷和外部一定有一个同步的目录!
查看一下卷挂载的路径
测试一下刚才的文件是否同步出去了!
这种方式使用的十分多,因为我们通常会构建自己的镜像!
假设构建镜像的时候没有挂载卷,要手动镜像挂载 -v 卷名:容器内路径!
数据卷容器
多个mysql同步数据!
# 启动2个容器,通过我们刚才自己写的镜像启动
[root@linuxprobe ~]# docker run -it --name docker001 linuxprobe/centos:1.0
[root@linuxprobe ~]# docker run -it --name docker002 --volumes-from docker001 linuxprobe/centos:1.0
# 测试:可以删除docker001,查看一下docker002是否可以访问这个文件
# 测试依旧可以访问
多个mysql可以实现数据共享
[root@linuxprobe home]# docker run -d -p 3310:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
[root@linuxprobe home]# docker run -d -p 3310:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01 mysql:5.7
# 这个时候可以实现两个容器数据同步!
结论:
容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止。
但是一旦你持久化到了本地,这个时候,本地的数据是不会删除的!
DockerFile
DockerFile介绍
dockerfile 是用来构建docker镜像的文件!命令参数脚本!
构建步骤:
- 编写一个 dockerfile 文件
- docker build 构建成为一个镜像
- docker run 运行镜像
- docker push 发布镜像(DockerHub、阿里云镜像仓库!)
查看一下官方是怎么做的
很多官方镜像都是基础包,很多功能没有,我们通常会自己搭建自己的镜像!
DockerFile构建过程
基础知识:
- 每个保留关键字(指令)都必须是大写字母
- 执行从上到下顺序执行
-
表示注释
- 每一个指令都会创建提交一个新的镜像层,并提交!
dockerfile是面向开发的,以后要发布项目,做镜像,就需要编写dockerfile文件,这个文件十分简单!
Docker镜像逐渐成为了企业交付的标准,必须要掌握!
步骤:开发,部署,运维。。。缺一不可!
DockerFile:构建文件,定义了一切的步骤,源代码
DockerImages:通过DockerFile构建生成的镜像,最终发布和运行产品
Docker容器:容器就是镜像运行起来提供服务器
DockerFile的指令
FROM # 基础镜像,一切从这里开始构建
MAINTAINER # 镜像是谁写的,姓名+邮箱
RUN # 镜像构建的时候需要运行的命令
ADD # 步骤,tomcat镜像,这个tomcat压缩包 添加内容
WORKDIR # 镜像的工作目录
VOLUME # 挂载的目录
EXPOSE # 暴露端口配置
CMD # 指定这个容器启动的时候要运行的命令 ,只有最后一个会生效,可被替代
ENTRYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令
ONBUILD # 当构建一个被继承 DockerFile 这个时候就会运行 ONBULD 的指令,出发指令
COPY # 类似ADD,将我们的文件拷贝到镜像中
ENV # 构建的时候设置环境变量
实战测试
Docker Hub 中99%的镜像都是从这个基础镜像过来的 FROM scratch ,然后配置需要的软件和配置来进行的构建
创建一个自己的centos
# 1、编写Dockerfile的文件
[root@linuxprobe dockerfile]# cat mydockerfile-centos
FROM centos
MAINTAINER yuanbao<1186286729@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
# 2、通过这个文件构建镜像
# 命令 docker build -f dockerfile文件路径 -t 镜像名:[tag]
Successfully built 3c6466fa24cc
Successfully tagged mydentos:0.1
# 3、测试运行
对比:之前原生的centos
我们可以列出本地镜像的变更历史
平时拿到一个镜像就可以研究它是怎么做的了?
CMD 和 ENTRYPOINT 区别
CMD # 指定这个容器启动的时候要运行的命令 ,只有最后一个会生效,可被替代
ENTRYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令
测试cmd
[root@linuxprobe dockerfile]# vim dockerfile-cmd-test
FROM centos:7
CMD ["ls","-a"]
# 构建镜像
[root@linuxprobe dockerfile]# docker build -f dockerfile-cmd-test -t cmdtest .
# run运行,发现我们的 ls -a 命令生效
[root@linuxprobe dockerfile]# docker run d4036e105735
.
..
.dockerenv
anaconda-post.log
bin
dev
etc
home
lib
# 想追加一个命令 -l ls -al
[root@linuxprobe dockerfile]# docker run d4036e105735 -l
docker: Error response from daemon: OCI runtime create failed: container_linux.go:380: starting container process caused: exec: "-l": executable file not found in $PATH: unknown.
# cmd 的情况下 -l 替换了 CMD ["ls","-a"] 命令,-l 不是命令所以报错!
测试 ENTRYPOINT
[root@linuxprobe dockerfile]# vim dockerfile-cmd-entrypoint
FROM centos:7
ENTRYPOINT ["ls","-a"]
[root@linuxprobe dockerfile]# docker build -f dockerfile-cmd-entrypoint -t entrypointtest .
Sending build context to Docker daemon 4.096kB
Step 1/2 : FROM centos:7
---> eeb6ee3f44bd
Step 2/2 : ENTRYPOINT ["ls","-a"]
---> Running in bb95719e841e
Removing intermediate container bb95719e841e
---> 7e3585974736
Successfully built 7e3585974736
Successfully tagged entrypointtest:latest
[root@linuxprobe dockerfile]# docker run 7e3585974736
.
..
.dockerenv
anaconda-post.log
bin
dev
etc
home
lib
lib64
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
# 我们的追加命令,是直接拼接在 ENTRYPOINT 命令后面
[root@linuxprobe dockerfile]# docker run 7e3585974736 -l
total 12
drwxr-xr-x 1 root root 6 Mar 1 07:13 .
drwxr-xr-x 1 root root 6 Mar 1 07:13 ..
-rwxr-xr-x 1 root root 0 Mar 1 07:13 .dockerenv
-rw-r--r-- 1 root root 12114 Nov 13 2020 anaconda-post.log
lrwxrwxrwx 1 root root 7 Nov 13 2020 bin -> usr/bin
drwxr-xr-x 5 root root 340 Mar 1 07:13 dev
drwxr-xr-x 1 root root 66 Mar 1 07:13 etc
drwxr-xr-x 2 root root 6 Apr 11 2018 home
lrwxrwxrwx 1 root root 7 Nov 13 2020 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Nov 13 2020 lib64 -> usr/lib64
drwxr-xr-x 2 root root 6 Apr 11 2018 media
drwxr-xr-x 2 root root 6 Apr 11 2018 mnt
drwxr-xr-x 2 root root 6 Apr 11 2018 opt
dr-xr-xr-x 128 root root 0 Mar 1 07:13 proc
dr-xr-x--- 2 root root 114 Nov 13 2020 root
drwxr-xr-x 11 root root 148 Nov 13 2020 run
lrwxrwxrwx 1 root root 8 Nov 13 2020 sbin -> usr/sbin
drwxr-xr-x 2 root root 6 Apr 11 2018 srv
dr-xr-xr-x 13 root root 0 Mar 1 07:13 sys
drwxrwxrwt 7 root root 132 Nov 13 2020 tmp
drwxr-xr-x 13 root root 155 Nov 13 2020 usr
drwxr-xr-x 18 root root 238 Nov 13 2020 var
Dockerfile中很多命令都十分相似,需要了解区别,最好的学习就是对比它们然后测试效果!
实战:Tomcat镜像
1、准备镜像文件 tomcat 压缩包,jdk的压缩包!
2、编写dockerfile文件,官方命名 Dockerfile
,build 会自动寻找这个文件,就不需要 -f 指定了!
[root@linuxprobe yuanbao]# vim Dockerfile
COPY readme.txt /usr/local/readme.txt
ADD jdk-8u321-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-9.0.59.tar.gz /usr/local/
RUN yum -y install vim
ENV MYPATH /usr/local
WORKDIR $MYPATH
ENV JAVA_HOME /usr/local/jdk1.8.0_321
ENV CLASSPATH $JAVA_HOME/lib.dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.59
ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.59
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
EXPOSE 8080
CMD /usr/local/apache-tomcat-9.0.59/bin/startup.sh && tail -F /url/local/apache-tomcat-9.0.59/bin/logs/catalina.out
3、构建镜像
# docker build -t diytomcat .
4、启动镜像
5、访问测试
6、发布项目(由于做了卷挂载,我们直接)
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
</web-app>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>hello,yuanbao</title>
</head>
<body>
Hello World!<br/>
<%
System.out.println("----my test web logs----");
%>
</body>
</html>
docker run -d -p 9090:8080 --name yuanbaotomcat6 -v /home/yuanbao/test/WEB-INF:/usr/local/apache-tomcat-9.0.59/webapps/test -v /home/yuanbao/tomcatlogs/:/usr/local/apache-tomcat-9.0.59/logs diytomcat
发现:项目部署成功,可以直接访问ok!
我们以后开发的步骤:需要掌握Dockerfile的编写!之后的一切都是用docker镜像来发布运行!
发布自己的镜像
DockerHub
1、地址:https://hub.docker.com/ 注册自己的账号!
2、确定这个账号可以登陆
3、在我们的服务器上提交自己的镜像
[root@linuxprobe home]# 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@linuxprobe home]# docker login -u kodakku
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
4、登陆完毕后就可以提交镜像了,就是一步 docker push
# push自己的镜像到服务器上面!
[root@linuxprobe home]# docker push diytomcat
Using default tag: latest
The push refers to repository [docker.io/library/diytomcat]
8e10b60e4630: Preparing
bac617ae4a9b: Preparing
349908d5cce0: Preparing
94b615fb0a9e: Preparing
174f56854903: Preparing
denied: requested access to the resource is denied # 拒绝
# push镜像的问题
[root@linuxprobe home]# docker push yuanbao/diytomcat:1.0
The push refers to repository [docker.io/yuanbao/diytomcat]
An image does not exist locally with the tag: yuanbao/diytomcat
# 解决:增加一个 tag (kodakku 为 DockerHub 账号)
[root@linuxprobe home]# docker tag a22e626ad7dc kodakku/tomcat:1.0
# docker push上去即可!自己发布的镜像尽量带版本号
[root@linuxprobe home]# docker push kodakku/tomcat:1.0
The push refers to repository [docker.io/kodakku/tomcat]
8e10b60e4630: Pushed
bac617ae4a9b: Pushed
349908d5cce0: Pushed
94b615fb0a9e: Pushed
174f56854903: Pushed
提交的时候也是按照镜像的层级来进行提交的!
阿里云镜像服务器上
1、登陆阿里云
2、找到镜像服务
3、创建命名空间
4、创建容器镜像
5、浏览阿里云
阿里云容器镜像的就参考官方地址!
小结
Docker 网络
理解Docker0
清空所有环境
测试
三个网络
# 问题: docker 是如何处理容器网络访问的?
[root@linuxprobe ~]# docker run -d -P --name tomcat01 tomcat
# 进入容器并安装网络工具,因为tomcat里没有网络工具和yum
root@4865e9059fec:/usr/local/tomcat# docker exec -it 4865e9059fec /bin/bash
root@4865e9059fec:/usr/local/tomcat# apt update
root@4865e9059fec:/usr/local/tomcat# apt install -y iproute2
root@4865e9059fec:/usr/local/tomcat# apt install -y net-tools
root@4865e9059fec:/usr/local/tomcat# apt install -y iputils-ping
# 查看容器的内部网络地址 ip addr , 发现容器启动的时候回等到一个 eth0@if143 ip地址,docker分配的!
[root@linuxprobe ~]# docker exec -it 4865e9059fec ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
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
142: eth0@if143: <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@linuxprobe ~]# 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.201 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.060 ms
# linux 可以 ping 通 docker 容器内部
原理
1、我们每启动一个docker容器,docker就会给docker容器分配一个ip,我们只要安装了docker,就会有一个网卡docker0 桥接模式,使用的技术是 evth-pair技术!
再次测试ip addr
2、再启动一个容器测试,发现又多了一对网卡!
# 我们发现这个容器带来网卡,是一对对的
# evth-pair 就是一对的虚拟设备接口,他们都是成对出现的,一端连着协议,一端彼此相连
# 正因为有这个特性,evth-pair 充当一个桥梁,连接各种虚拟网络设备的
# OpenStac,Docker容器之间的连接,OVS的连接,都是使用evth-pair技术
3、我们来测试下 tomcat01 和 tomcat02 是否可以ping通?
[root@linuxprobe ~]# docker exec -it tomcat02 ping 172.17.0.3
# 结论:容器和容器之间是可以互相 ping 通的!
绘制一个网络模型图
结论:tomcat01 和tomcat02 是公用的一个路由器,docker0 。
所有的容器不指定网络的情况下,都是 docker0 路由的,docker会给我们的容器分配一个默认的可用IP
小结
Docker使用的是linux的桥接,宿主机中是一个Docker容器的网桥 docker0 。
Docker中的所有的网络接口都是虚拟的。虚拟的接口转发效率搞!(内网传递文件!)
只要容器删除,对应的网桥一对就没了!
--link
思考一个场景,我们编写了一个微服务,datebase url=ip: , 项目不重启,数据库ip换掉了,我们希望可以处理这个问题,可以通过名字来进行访问容器 ?
[root@linuxprobe ~]# docker exec -it tomcat02 ping tomcat01
ping: tomcat01: Name or service not known
# 如何可以解决呢?
# 通过 --link 就可以解决了网络连通问题
[root@linuxprobe ~]# docker run -d -P --name tomcat03 --link tomcat02 tomcat
d3ccad14168dbf51daea2dfebfbeebe69d48d887b9545403d3983fe84df60109
[root@linuxprobe ~]# 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.107 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.262 ms
# 反向可以ping通吗?
[root@linuxprobe ~]# docker exec -it tomcat02 ping tomcat03
ping: tomcat03: Name or service not known
探究:inspect
其实这个tomcat03 就是在本地配置了tomcat02的配置?
# 查看 hosts 配置,在这里原理发现!
[root@linuxprobe ~]# 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 f3a6ad2c5c3a
172.17.0.4 d3ccad14168d
本质探究:--link 就是我们在 hosts 配置中增加了一个 172.17.0.3 tomcat02 f3a6ad2c5c3a
我们现在玩 Docker 已经不建议使用 --link 了!
现在都用自定义网络!不用 docker0 !
docker0问题:不支持容器名连接访问!
自定义网络
查看所有的docker网络
网络模式
bridge:桥接 docker 搭桥 (默认,自己创建也使用 bridge 模式)
none:不配置网络
host:和宿主机共享网络
container:容器网络连通!(用的少!局限很大)
测试
# 我们直接启动的命令 --net bridge ,而这个就是 docker0
docekr run -d -P --name tomcat01 tomcat
docekr run -d -P --name tomcat01 --net bridge tomcat
# docker0 特点:默认的,域名不能访问,--link可以打通连接!
# 我们可以自定义一个网络!
# --driver bridge
# --subnet 192.168.0.0/16
# --gateway 192.168.0.1
[root@linuxprobe ~]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
b3852400da33e1dcfba29c812407396f5d93846dd36f30d50a13fbd9057c3057
[root@linuxprobe ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
271065b7977c bridge bridge local
a7a10db9a740 host host local
b3852400da33 mynet bridge local
23802e091565 none null local
我们自己的网络就创建好了!
[root@linuxprobe ~]# docker run -d -P --name tomcat-net-01 --net mynet tomcat
2a02dd496415ec157a35562926e18a0aaad02397cbe2a47e9056cdd26d92e02a
[root@linuxprobe ~]# docker run -d -P --name tomcat-net-02 --net mynet tomcat
2f2e43d7a4b934dd612051866d3d71f603d7108f8005e27d89f2b458517053fc
[root@linuxprobe ~]# docker network inspect mynet
[
{
"Name": "mynet",
"Id": "b3852400da33e1dcfba29c812407396f5d93846dd36f30d50a13fbd9057c3057",
"Created": "2022-03-08T16:50:05.555707312+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": {
"2a02dd496415ec157a35562926e18a0aaad02397cbe2a47e9056cdd26d92e02a": {
"Name": "tomcat-net-01",
"EndpointID": "7606f8770dbbf67f57b285da4f38c9de7b182f320447a375838db1daf9a7b31f",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/16",
"IPv6Address": ""
},
"2f2e43d7a4b934dd612051866d3d71f603d7108f8005e27d89f2b458517053fc": {
"Name": "tomcat-net-02",
"EndpointID": "96f6604daa08936ae35fc0acf6a60e503bed73e1f61f360037c07b72c3672bcf",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
# 再次测试ping连接
[root@linuxprobe ~]# 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.058 ms
64 bytes from 192.168.0.3: icmp_seq=2 ttl=64 time=0.044 ms
^C
--- 192.168.0.3 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 0.044/0.051/0.058/0.007 ms
# 现在不使用--link 也可以ping名字了!
[root@linuxprobe ~]# 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.095 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.159 ms
^C
--- tomcat-net-02 ping statistics ---
我们自定义的网络docker都已经帮我们维护好了对应的关系,推荐我们平时这样使用网络!
好处:redis - mysql- 不同的集群使用不同的网络,保证集群是安全和健康的
网络连通
# 测试打通 tomca01 - mynet
# 连通之后就是将 tomcat01 放到了 mynet 网络下
# 一个容器两个ip地址!
# 阿里云服务器:公网ip 私网ip
[root@linuxprobe ~]# 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.071 ms
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.094 ms
# tomcat02 是依旧打不通的
[root@linuxprobe ~]# docker exec -it tomcat02 ping tomcat-net-01
ping: tomcat-net-01: Name or service not known
结论:假设需要跨网络操作别人,就需要使用docker network connect 连通!
实战:部署Redis集群
shell脚本!
# 创建网卡
docker network create redis --subnet 172.38.0.0/16
# redis-cli 访问
docker run -it --link myredis:redis --rm redis redis-cli -h redis -p 6379
# 通过脚本创建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 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
# 用for循环启动√
== 启动容器===
for port in $(seq 1 6); \
do \
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; \
done
==进入其中一个容器===
docker exec -it redis-1 /bin/sh
==创建集群===
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
# 集群配置完毕
/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 --cl
uster-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: 05b721d8be4fe69d3b9bfcea4487d2d060d337da 172.38.0.11:6379
slots:[0-5460] (5461 slots) master
M: f5421c0ae2d971c6d0c8405d4656c9ad9dcfbf7f 172.38.0.12:6379
slots:[5461-10922] (5462 slots) master
M: 5f7f5f9599b1a9306eefc8cdb663971f3ffd2a40 172.38.0.13:6379
slots:[10923-16383] (5461 slots) master
S: 7893dac761be51128741ad02d4ca81ab27cf84d4 172.38.0.14:6379
replicates 5f7f5f9599b1a9306eefc8cdb663971f3ffd2a40
S: ae7fcd1edd25cc0bddb8bba472ff1a823c323326 172.38.0.15:6379
replicates 05b721d8be4fe69d3b9bfcea4487d2d060d337da
S: 893b4619d5c813d0d99585052314546634ce69f7 172.38.0.16:6379
replicates f5421c0ae2d971c6d0c8405d4656c9ad9dcfbf7f
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: 05b721d8be4fe69d3b9bfcea4487d2d060d337da 172.38.0.11:6379
slots:[0-5460] (5461 slots) master
1 additional replica(s)
M: 5f7f5f9599b1a9306eefc8cdb663971f3ffd2a40 172.38.0.13:6379
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
M: f5421c0ae2d971c6d0c8405d4656c9ad9dcfbf7f 172.38.0.12:6379
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
S: 893b4619d5c813d0d99585052314546634ce69f7 172.38.0.16:6379
slots: (0 slots) slave
replicates f5421c0ae2d971c6d0c8405d4656c9ad9dcfbf7f
S: ae7fcd1edd25cc0bddb8bba472ff1a823c323326 172.38.0.15:6379
slots: (0 slots) slave
replicates 05b721d8be4fe69d3b9bfcea4487d2d060d337da
S: 7893dac761be51128741ad02d4ca81ab27cf84d4 172.38.0.14:6379
slots: (0 slots) slave
replicates 5f7f5f9599b1a9306eefc8cdb663971f3ffd2a40
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
docker 搭建 redis 集群完成!
我们使用了docker之后,所有的技术都会慢慢的变的简单起来!
SpringBoot 微服务打包 Docker 镜像
1、构建springboot微服务项目
2、打包应用
3、编写dockerfile
4、构建镜像
5、发布运行