Docker 概述

docker 学习

  • docker概述
  • docker安装
  • docker命令
    • 镜像命令
    • 容器命令
    • 操作命令
    • ….
  • docker 镜像!
  • 容器数据卷!
  • dockerfile
  • docker网络原理
  • IDEA 整合 docker
  • docker compose
  • docker swarm
  • CI\CD jenkins

Docker 概述

docker 为什么会出现?

一款产品:开发-上线 两套环境! 应用环境,应用配置

开发 —- 运维。问题:在我电脑上是可以运行的。为啥线上失败

环境配置十分麻烦,每一个机器都要部署环境,(集群redis、es、hadoop—)费时

发布一个项目(jar+(redis—+mysql+jdk + es))

传统:开发jar,运维来做。

现在:开发大宝部署上线,一套流程做完!

java —apk — 发布(应用商店)—-张三使用apk—-安装即可

java —- jar(环境)—-大宝项目带上环境(镜像)—- (docker仓库:商店)—–下载我们发布的镜像—— 直接运行即可!

docker 给以上的问题,提出了解决方案!

docker 的思想就是来自于集装箱!

jre — 多个应用(端口冲突)—-原来都是交叉的

隔离:docker核心思想。打包装箱。每个箱子是互相隔离的。

docker 通过隔离机制,可以将服务器利用到极致!

本质:所有的技术都是因为出现了一些问题,我们需要解决,才去学习;

docker 的历史

2010 年,几个搞it的年轻人。就在美国成立了一家dotcloud

做一写pass的云计算服务,lxc有关的容器技术;

docker 安装

docker 基本组成

img

docker 安装

docker 国内阿里云镜像地址:

# 设置docker 镜像的仓库:国内阿里
sudo yum-config-manager \
			--add-repo \
			https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

# 安装docker相关的包 docker-ce 社区版本  ee 企业版本
sudo yum install docker-ce docker-ce-cli containerd.io

docker uninstall、卸载docker

# 删除docker 软件
sudo yum remove docker-ce docker-ce-cli containerd.io
# 删除docker 运行资源
sudo rm -rf /var/lib/docker
sudo rm -rf /var/lib/containerd

国内阿里云镜像加速

1、登录阿里云,找到镜像加速

https://markdown-upload-picture.oss-cn-beijing.aliyuncs.com/markdown/%E6%88%AA%E5%B1%8F2021-09-13%20%E4%B8%8A%E5%8D%889.59.02.png

截屏2021-09-13 上午10.15.30

上边就是镜像加速的配置。

docker 底层原理

docker 是怎么工作的?

docker 是一个 c-s结构的系统,docker 的守护进程运行在主机上。通过socket从客户端访问!

dockerserver 接收到docker-client的指令,就会去执行这个指令。

image-20210913103314535

docker 为什么比vm快

  1. docker 有着比虚拟机更少的抽象层

  2. docker 利用的是宿主机的内核,vm需要时guest os。

    image-20210913102623021

所以说,新建一个容器的时候,docker 不需要像虚拟机一样重新加载一个操作系统内核,避免引导。虚拟机是加载guest os,分钟级别的,docker 是利用宿主机的操作系统,省略了这个复杂的过程,秒级。

docker 的常用命令

帮助命令

docker verison	# docker 的版本信息
docker info 		# docker 的系统信息,包括容器镜像的数量
docker 命令 --help # 帮助命令

官方命令帮助文档:https://docs.docker.com/reference/

镜像命令

docker images 查看所有本地的主机上的镜像

# docker images
REPOSITORY                           TAG                 IMAGE ID            CREATED             SIZE
quay.io/coreos/flannel               v0.14.0             8522d622299c        3 months ago        67.9MB

# 解释:
REPOSITORY	镜像的仓库源
TAG					镜像的标签
IMAGE ID		镜像的id
CREATED			镜像的创建时间
SIZE				镜像大小

# 可选项
Options:
  -a, --all             Show all images (default hides intermediate images)
      --digests         Show digests
  -f, --filter filter   Filter output based on conditions provided
      --format string   Pretty-print images using a Go template
      --no-trunc        Don't truncate output
  -q, --quiet           Only show numeric IDs

docker search 搜索镜像

$ docker search mysql
NAME                              DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
mysql                             MySQL is a widely used, open-source relation…   11404               [OK]

# 可选项
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

--filter=STARS=3000 # 搜索STARS大于3000的

docker pull 下载镜像

$ docker pull nginx
Using default tag: latest # 如果不写tag,默认就是latest
latest: Pulling from library/nginx
a330b6cecb98: Pull complete	# 分层下载,docker image 的核心,联合文件系统
e0ad2c0621bc: Pull complete
9e56c3e0e6b7: Pull complete
09f31c94adc6: Pull complete
32b26e9cdb83: Pull complete
20ab512bbb07: Pull complete
Digest: sha256:853b221d3341add7aaadf5f81dd088ea943ab9c918766e295321294b035f3f3e # 签名
Status: Downloaded newer image for nginx:latest # 真实地址

docker rmi 删除镜像

docker rmi -f 容器id	# 删除容器镜像
docker rmi -f 容器id 容器id 容器id	# 删除多个容器镜像
docker rmi -f $(docker images -qa) # 删除全部容器镜像

容器命令

docker run 创建容器

docker run [可选参数] image

# 参数说明
--name="Name" 容器名字
-d			后台方式
-it			使用交互方式运行,进入容器内部查看
-p
	-p ip:主机端口:容器端口
	-p 主机端口:容器端口
	-p 容器端口
	容器端口
-P			随机指定端口


# 启动并进入容器
# 退出之后容器停止运行
docker run -it centos /bin/bash



docker ps 列出运行的容器

docker ps 		显示当前运行的容器
docker ps -a  显示所有容器


退出容器

exit		直接退出并停止容器
Ctrl + p + q    容器不停止退出

删除容器

docker rm 容器id		# 删除指定容器,rm -f 删除正在运行的容器
docker rm -f	$(docker ps -aq)		# 删除所有容器
docker ps -qa | xargs docker rm  # 删除所有容器

启动和停止容器

docker start 容器id		# 启动容器
docker stop 容器id		# 停止容器
docker restart 容器id		# 重启容器
docker kill 容器id			# 停止容器

常用其他命令

# 后台启动
docker run -d 容器id
# 问题,docker ps 发现容器停止了
# 常见的坑,docker 容器使用后台运行,就必须要有一个前台进程,docker发现没有应用,就会自动停止
# nginx,容器启动后,发现在即没有提供服务,就会立刻停止,就没有程序了

查看日志

docker logs -f -t --tail 日志条数  容器id

查看容器中进程信息ps

docker top 容器id

查看镜像的元数据

docker inspact 容器id

进入当前运行的容器

docker exec -it 容器id bashShell			# 进入容器后开启一个新的终端,可以在里边凑走


# 方式二
docker attach 容器id  # 进入容器正在执行的终端,不会启动新的进程

拷贝容器中的文件到主机

docker cp 容器id:/文件路径  本地路径

小结

attach				# 当前shell下,attach 链接指定运行镜像
build					# 通过dockerfile定制镜像
commit				# 提交当前容器为新的镜像
cp						# 从容器中拷贝指定文件或者目录到宿主机中
create 				# 创建一个新的容器,同run,但不启动容器
diff					# 查看docker容器变化
events				# 从docker服务器获取容器实时事件
exec					# 在已存在的容器上运行命令
export				# 到处容器的内容流作为一个tar归档文件 对应import
history				# 展示一个镜像形成历史
images				# 列出系统当前镜像
import				# 从tar包中的内容创建一个新的文件系统影像
info					# 显示系统相关信息
inspect				# 查看容器详细信息
kill					# kill指定容器
load					# 从一个tar文件加载镜像
login					# 登陆一个docker源服务器
logout				# 从当前docker registry退出
logs					# 输入容器日志信息
port					# 查看映射端口对应的容器内部源端口
pause					# 暂停容器
pull					# 拉取镜像
push					# 推送镜像至源服务器
restart				# 重启容器
rm						# 删除容器
rmi						# 删除镜像
run						# 运行容器
save					# 保存镜像为tar包
search				# 搜索镜像  在docker hub中
start					# 启动容器
stop					# 停止容器
tag						# 给镜像打标签
top						# 查看容器中运行的进程信息
unpause				# 取消暂停容器
version				# 查看docker版本号
wait					# 截取容器停止时的退出状态值

docker 启动nginx

docker pull nginx

docker images 

docker run -d --name nginx01 -p 3344:80  nginx

# 主机的 3344 映射到容器的80

docker 启动tomcat

# 官方使用
docker run -it --rm tomcat:9.0
# 注释,--rm 用完即删除,用来测试

# 自己启动
docker run -d -p 3355:8080 --name tomcat01 tomcat:9.0

部署ES+kibana

# 官方命令,docker hub
$ docker network create somenetwork
$ docker run -d --name elasticsearch --net somenetwork -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2

# es 暴露的端口很多
# es 十分的耗内存
# es 的数据一般需要放置到安全目录!挂载
# --net somenetwork  网络配置

# 查看docker容器内存使用
$ docker stats

# 配置es内存限制
$ docker run -d --name elasticsearch --net somenetwork -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.6.2


可视化

  • 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 镜像讲解

镜像是什么

镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。

所有的应用,直接打包docker镜像,就可以直接跑起来。

如何得到镜像:

  • 远程仓库下载
  • 朋友拷贝
  • 自己制作dockerfile

Docker 镜像加载原理

UnionFS (联合文件系统)

UnionFS :union文件系统是一种分层、轻量级并且高性能的文件系统,它支持度i文件系统 的修改,作为一次提交来一层层的叠加,同时可以将不同目录挂载到哦同一个虚拟文件系统下。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就是各种不同的操作系统发行版,比如Ubuntu,Centos等等。

平时我们安装进虚拟机的CentOS都是好几个G,为什么Docker这里才200M?

对于一个精简的OS,rootfs可以很小,只需要包含最基本的命令,工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供rootfs就可以了。由此可见对于不同的linux发行版,bootfs基本是一致的,rootfs会有差别,因此不同的发行版可以共用bootfs;

分层理解

分层的镜像

我们可以去下载一个镜像,注意观察下载的日志输出,可以看到是一层一层的在下载。

思考:为什么docker镜像要采用这种分层结构呢?

最大的好处,我觉得是资源共享。

。。。。。。

commit镜像

docker commit 提交容器成为一个新的副本

# 命令和git原理类似
docker commit -m="提交的描述信息" -a="作者" 容器id 目标镜像名:[TAG]

容器数据卷

什么是容器数据卷

docker 的理念回顾

将应用和环境打包成一个镜像!

数据?如果数据都在容器中,那么我们容器删除,数据就会丢失!需求:数据可以持久化

MYSQL,容器删了,删库跑路!需求:MYSQL 数据可以存储在本地!

容器之间可以有一个数据共享的技术!Docker 容器中产生的数据,同步到本地!这就是卷技术!目录的挂载,将我们容器内的目录,挂载到 Linux 上面!

总结一句话:容器的持久化和同步操作!容器间也是可以数据共享的

部署mysql

Mysql 的数据持久化问题

# 获取镜像
[rootakuangshen home] # docker pull mysql: 5.7

# 运行容器,需要数据!#安装启动 mysq1, 需要配置密码的,这是要汪意点!
# 官方试:docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag

# 启动我们的 
-d 后台运行 
-p 端口映射
-v 卷挂载
-e 环境配置
--name 容器名
[rootakuangshen home]# docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/ib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7

具名挂载和匿名挂载

# 匿名挂载
-v 容器内路径
docker run -d -p --name nginx01 -v /ect/nginx nginx

# 查看所有的 volume 的情况
$ docker volume  ls
local  9f38292179faal78afcce54d80be99d4ddd68c91d2a68870bcece72d2b7ed061

# 这里发现,这种就是匿名挂,我们在 -v 只写了容器内的路径,没有写容器外的路径

# 具名挂载
[root@guangshen home] # docker run  name nginx -v juming-nginx:/etc/nginx nginx
[root@kuangshen home] # docker volume ls  
DRIVER  VOLUME NAME
local   juming-nginx

# 通过 -v 卷名:容器内路径
# 查看一下这个卷
$ 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 只要看到ro就说明这个路径只能通过宿主机来操作,容器内部是无法操作的;

初识dockerfile

Dockerfile。就是用来构建 docker 镜像的构建文件!命令脚本!先体验一下

通过这个脚本可以生成镜像,镜像是一层一层的,脚本ー个个的命令,每个命令都是一层

# 创建一个 dockerfile 文件,名字可以随机建议 Dockerfie
# 文件中的内容  指令(大写)参数

 FROM Centos

 VOLUME ["volume01", "volume02"]  
 CMD echo "----end------"
 CMD /bin/bash

# 这里的每个命令,就是镜像的一层

# 构建镜像
docker build -f /home/dockerfile -t kuangshen/centos:1.0 .

数据卷容器

多个mysql同步数据

image-20210913181135318

启动3个容器,通过我们刚才自己的写镜像启动

docker run -it --name docker01 centos

docker run -it --name docker02 --volumes-from docker01 centos

docker run -it --name docker03 --volumes-from docker01 centos

测试:可以删除docker01,查看下docker02和docker03是否还可以访问这个文件

测试依旧可以访问

image-20210913183443574

结论

容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止但是一旦你持久化到了本地,这个时候,本地的数据是不会删除的!

DockerFile

docker file 介绍

Dockerfile 是用来构建 docker 镜像的文件!命令参数脚本

构建步骤:

1、编写一个 dockerfile 文件

2、docker build 构建成为一个镜像

3、docker run 运行镜像

4、docker push 发布镜像(Dockerhub、阿里云镜像仓库!)

docker file 构建过程

基础知识:

1、每个保留关键字(指令)都是必须是大写字母

2、执行从上到下顺序执行

3、#表示注释

4、每一个指令都会创建提交一个新的镜像层,并提交

image-20210913235400018

dockerfile 是面向开发的,我们以后要发布项目,做镜像,就需要编写dockerfile文件,这个文件十分简单。

Docker 镜像逐渐成为企业交付的标准,必须要掌握!

步骤:开发,部署,运维。。。缺一不可!

Dockerfile:构建文件,定义了一切的步骤,源代码

Dockerimages:通过 Dockerfile 构建生成的镜像,最终发布和运行的产品

Docker 容器:容器就是镜像运行起来提供服务器

docker file 的指令

以前的话我们就是使用別人的,现在我们知道了这些指令后,我们来练习自己写一个镜像!

FROM 								# 基础镜镜像,一切从这里开始构建  
MAINTAINER 					# 并镜像是谁写的,姓名+邮箱  
RUN 								# 镜像构建的时候需要运行的命令  
ADD 								# 添加文件并且解压;步骤:tomcats 镜像,这个 tomcat 压缩包!添加内容  
WORKDIR 						# 镜像的工作目录  
VOLUME 							# 挂载的目录  
EXPOSE 							# 开放端口配置
CMD									# 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT					# 指定这个容器启动的时候要运行的命令,可以追加命令
ONBUILD							# 当构建一个被继承 Dockerfile 这个时候就会运行 ONBUILD 的指令。触发指令
COPY								# 类似 ADD,将我们文件携贝到镜像中
ENV									# 构建的时候设置环境变量

实战测试

docker hub 中99%镜像都是从这个基础镜像过来的FROM scratch,然后配置需要的软件和配置来进行构建

创建一个自己的centos

# 编写dockerfile 的文件
$ cat myDockerFileCentos
FROM centos
MAINTAINER haitian
ENV MYPATH /usr/local

WORKDIR $MYPATH
RUN /bin/sh -c  'yum -y install vim net-tools; yum clean all'
CMD echo $MYPATH
CMD echo "----------"
CMD /bin/bash

# 构建镜像
# docker build -f dockerfile文件路径 -t 镜像名:[tag] .   这个.是上下文环境
docker build -f myDockerFileCentos -t mysqlcentos:0.1 .

通过 history 查看镜像构建过程

[root@ip-172-31-43-53 dockerfile]# docker history nginx:latest
IMAGE          CREATED       CREATED BY                                      SIZE      COMMENT
ad4c705f24d3   4 days ago    /bin/sh -c #(nop)  CMD ["nginx" "-g" "daemon…   0B
<missing>      4 days ago    /bin/sh -c #(nop)  STOPSIGNAL SIGQUIT           0B
<missing>      4 days ago    /bin/sh -c #(nop)  EXPOSE 80                    0B
<missing>      4 days ago    /bin/sh -c #(nop)  ENTRYPOINT ["/docker-entr…   0B
<missing>      4 days ago    /bin/sh -c #(nop) COPY file:09a214a3e07c919a…   4.61kB
<missing>      4 days ago    /bin/sh -c #(nop) COPY file:0fd5fca330dcd6a7…   1.04kB
<missing>      4 days ago    /bin/sh -c #(nop) COPY file:0b866ff3fc1ef5b0…   1.96kB
<missing>      4 days ago    /bin/sh -c #(nop) COPY file:65504f71f5855ca0…   1.2kB
<missing>      4 days ago    /bin/sh -c set -x     && addgroup --system -…   64MB
<missing>      4 days ago    /bin/sh -c #(nop)  ENV PKG_RELEASE=1~buster     0B
<missing>      4 days ago    /bin/sh -c #(nop)  ENV NJS_VERSION=0.6.2        0B
<missing>      4 days ago    /bin/sh -c #(nop)  ENV NGINX_VERSION=1.21.3     0B
<missing>      10 days ago   /bin/sh -c #(nop)  LABEL maintainer=NGINX Do…   0B
<missing>      11 days ago   /bin/sh -c #(nop)  CMD ["bash"]                 0B
<missing>      11 days ago   /bin/sh -c #(nop) ADD file:4ff85d9f6aa246746…   69.3MB

CMD 和 ENTRYPOINT 区别

CMD							# 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT			# 指定这个容器启动的时候要运行的命令,可以追加命令

测试cmd

# 编写dockerfile
[root@ip-172-31-43-53 dockerfile]# cat dockfilecentoscmd
FROM centos
CMD ["ls","-a"]


# 构建镜像
[root@ip-172-31-43-53 dockerfile]# docker build -f dockfilecentoscmd -t cmdtest .
Sending build context to Docker daemon  3.072kB
Step 1/2 : FROM centos
 ---> 300e315adb2f
Step 2/2 : CMD ["ls","-a"]
 ---> Running in 5fe48ffd6875
Removing intermediate container 5fe48ffd6875
 ---> fdca2452fc82
Successfully built fdca2452fc82
Successfully tagged cmdtest:latest


# run 运行,
[root@ip-172-31-43-53 dockerfile]# docker run cmdtest
.
..
.dockerenv
bin
dev
etc
home
lib
lib64
lost+found
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var


# 想追加一个命令 -l   ls -al
[root@ip-172-31-43-53 dockerfile]# docker run cmdtest -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.
ERRO[0000] error waiting for container: context canceled

# cmd 的情况下 -l 替换了 CMD ["ls","-a"],-l 不是命令所以报错
# 这样就能运行了
[root@ip-172-31-43-53 dockerfile]# docker run cmdtest ls -al /root/
total 32
dr-xr-x---. 2 root root  162 Dec  4  2020 .
drwxr-xr-x. 1 root root    6 Sep 14 03:03 ..
-rw-r--r--. 1 root root   18 May 11  2019 .bash_logout
-rw-r--r--. 1 root root  176 May 11  2019 .bash_profile
-rw-r--r--. 1 root root  176 May 11  2019 .bashrc
-rw-r--r--. 1 root root  100 May 11  2019 .cshrc
-rw-r--r--. 1 root root  129 May 11  2019 .tcshrc
-rw-------. 1 root root 2328 Dec  4  2020 anaconda-ks.cfg
-rw-r--r--. 1 root root  435 Dec  4  2020 anaconda-post.log
-rw-------. 1 root root 2026 Dec  4  2020 original-ks.cfg

测试ENTRYPOINT

# 编写dockerfile
[root@ip-172-31-43-53 dockerfile]# cat dockfilecentoscmd
FROM centos
ENTRYPOINT ["ls","-a"]


# 构建镜像
[root@ip-172-31-43-53 dockerfile]# docker build -f dockfilecentoscmd -t cmdtest:1 .
Sending build context to Docker daemon  3.072kB
Step 1/2 : FROM centos
 ---> 300e315adb2f
Step 2/2 : ENTRYPOINT ["ls","-a"]
 ---> Running in f966e0b7d749
Removing intermediate container f966e0b7d749
 ---> 5081cd69f7b2
Successfully built 5081cd69f7b2
Successfully tagged cmdtest:1


# 运行镜像,追加参数 -l;实际效果是 ls -al
[root@ip-172-31-43-53 dockerfile]# docker run cmdtest:1 -l
total 0
drwxr-xr-x.   1 root root   6 Sep 14 03:06 .
drwxr-xr-x.   1 root root   6 Sep 14 03:06 ..
-rwxr-xr-x.   1 root root   0 Sep 14 03:06 .dockerenv
lrwxrwxrwx.   1 root root   7 Nov  3  2020 bin -> usr/bin
drwxr-xr-x.   5 root root 340 Sep 14 03:06 dev
drwxr-xr-x.   1 root root  66 Sep 14 03:06 etc
drwxr-xr-x.   2 root root   6 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   6 Dec  4  2020 lost+found
drwxr-xr-x.   2 root root   6 Nov  3  2020 media
drwxr-xr-x.   2 root root   6 Nov  3  2020 mnt
drwxr-xr-x.   2 root root   6 Nov  3  2020 opt
dr-xr-xr-x. 127 root root   0 Sep 14 03:06 proc
dr-xr-x---.   2 root root 162 Dec  4  2020 root
drwxr-xr-x.  11 root root 163 Dec  4  2020 run
lrwxrwxrwx.   1 root root   8 Nov  3  2020 sbin -> usr/sbin
drwxr-xr-x.   2 root root   6 Nov  3  2020 srv
dr-xr-xr-x.  13 root root   0 Sep 13 05:59 sys
drwxrwxrwt.   7 root root 145 Dec  4  2020 tmp
drwxr-xr-x.  12 root root 144 Dec  4  2020 usr
drwxr-xr-x.  20 root root 262 Dec  4  2020 var
结论

ENTRYPOINT 会直接追加到命令末尾,

CMD 是直接替换掉dockerfile中的命令

实战 tomcat 镜像

  1. 准备镜像文件 tomcat 压缩包,jdk压缩包

image-20210914120423784

  1. 编写dockerfile文件,官方命令 Dockerfile ,build 会自动寻找这个文件,就不需要-f指定了!
[root@ip-172-31-43-53 tomcat]# cat Dockerfile
FROM centos
MAINTAINER liulei

ADD jdk-8u73-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-9.0.22.tar.gz /usr/local/

RUN yum -y install vim

ENV MYPATH /usr/local
WORKDIR $MYPATH

ENV JAVA_HOME /usr/local/jdk1.8.0_73
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.22
ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.22
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin

EXPOSE 8080

CMD /usr/local/apache-tomcat-9.0.22/bin/startup.sh && tail -f /usr/local/apache-tomcat-9.0.22/logs/catalina.out
  1. 构建镜像
[root@ip-172-31-43-53 tomcat]# docker build -t selftomcat .
  1. 启动镜像
docker run -d -p 9090:8080 --name mytomcat -v /tmp/tomcat/test:/usr/local/apache-tomcat-9.0.22/webapps/test -v /tmp/tomcat/logs:/usr/local/apache-tomcat-9.0.22/logs selftomcat
  1. 访问测试
[root@ip-172-31-43-53 tomcat]# curl localhost:9090 --head
HTTP/1.1 200
Content-Type: text/html;charset=UTF-8
Transfer-Encoding: chunked
Date: Tue, 14 Sep 2021 04:33:57 GMT

  1. 发布项目(做了卷映射,本地就可以发布项目)
找一个简单的项目放里边就可以了。

发布自己的镜像 到 ECR

可以是公司私有镜像仓库,也可以是docker hub。这我用的aws 的ECR

# 创建仓库,点击 查看推送命令
# 登陆 ecr test 仓库
# 注意:需要先配置aws认证,然后才能登陆成功
aws ecr get-login-password --region cn-northwest-1 | docker login --username AWS --password-stdin 014782458769.dkr.ecr.cn-northwest-1.amazonaws.com.cn

# 标记我们要推送上去的镜像
# 将nginx 镜像重新标记
docker tag nginx:latest 014782458769.dkr.ecr.cn-northwest-1.amazonaws.com.cn/test:v1

# 推送镜像到ecr
~ docker push 014782458769.dkr.ecr.cn-northwest-1.amazonaws.com.cn/test:v1
The push refers to repository [014782458769.dkr.ecr.cn-northwest-1.amazonaws.com.cn/test]
fac15b2caa0c: Pushed
f8bf5746ac5a: Pushed
d11eedadbd34: Pushed
797e583d8c50: Pushed
bf9ce92e8516: Pushed
d000633a5681: Pushed
v1: digest: sha256:6fe11397c34b973f3c957f0da22b09b7f11a4802e1db47aef54c29e2813cc125 size: 1570

# 推送成功 014782458769.dkr.ecr.cn-northwest-1.amazonaws.com.cn/test:v1

image-20210914141639328

# 删除本地镜像,从镜像仓库拉取该镜像启动
docker rmi 014782458769.dkr.ecr.cn-northwest-1.amazonaws.com.cn/test:v1

# 启动
~ docker run 014782458769.dkr.ecr.cn-northwest-1.amazonaws.com.cn/test:v1
Unable to find image '014782458769.dkr.ecr.cn-northwest-1.amazonaws.com.cn/test:v1' locally
v1: Pulling from test
Digest: sha256:6fe11397c34b973f3c957f0da22b09b7f11a4802e1db47aef54c29e2813cc125
Status: Downloaded newer image for 014782458769.dkr.ecr.cn-northwest-1.amazonaws.com.cn/test:v1
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2021/09/14 06:18:58 [notice] 1#1: using the "epoll" event method
2021/09/14 06:18:58 [notice] 1#1: nginx/1.21.3
2021/09/14 06:18:58 [notice] 1#1: built by gcc 8.3.0 (Debian 8.3.0-6)
2021/09/14 06:18:58 [notice] 1#1: OS: Linux 5.10.47-linuxkit
2021/09/14 06:18:58 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2021/09/14 06:18:58 [notice] 1#1: start worker processes
2021/09/14 06:18:58 [notice] 1#1: start worker process 32
2021/09/14 06:18:58 [notice] 1#1: start worker process 33
2021/09/14 06:18:58 [notice] 1#1: start worker process 34
2021/09/14 06:18:58 [notice] 1#1: start worker process 35

发布到阿里云

发布到阿里云,参考阿里云官方文档;

小结

image-20210914144455074

docker 网络

docker0

image-20210914151010309

三个网络

问题:docker 是如何处理容器网络访问的?

# 启动容器
[root@ip-172-31-43-53 tomcat]# docker run -d -P selftomcat
d2c217fdd9c9f434775b31c8cd7236c366423150865f4bb61f188eb816be5441

# 主机起了一个网卡
[root@ip-172-31-43-53 tomcat]#  ip link show veth341dcfa
44: veth341dcfa@if43: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP mode DEFAULT group default
    link/ether d2:77:35:8b:27:1c brd ff:ff:ff:ff:ff:ff link-netnsid 1

# 查看容器的内部网络地址, ip addr,发现容器启动的时候会得到一个 eth0@if44 ip地址,docker分配的。
[root@ip-172-31-43-53 tomcat]# docker exec -it silly_blackwell 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
43: eth0@if44: <BROADCAST,MULTICAST,UP,LOWER_UP> 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

# 可以ping通
[root@ip-172-31-43-53 tomcat]# ping 172.17.0.3
PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data.
64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.051 ms
64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.033 ms
^C
--- 172.17.0.3 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.033/0.042/0.051/0.009 ms

原理:

  1. 启动docker容器,docker就会给docker容器分配一个ip。我们只要安装了docker,就会有一个网卡docker0;

    它是桥接模式,用的是veth-pair技术!

    Veth设备的作用主要用来连接两个网络命名空间,如同一对网卡中间连着一条网线。既然是一对网卡,那么其中一块网卡称作另一块的peer。在Veth设备的一端发送数据会直接发送到另一端。

  2. 如果我们再启动一个容器,会发现又多一对网卡

# 我们发现容器带来的网卡,都是一对一对的
# veth-pair 就是一对虚拟设备接口,她们都是成对出现的,一段连着协议,一段彼此相连
# 正因为有这个特性,veth-pair充当一个桥梁,连接各种虚拟设备
# openstac,docker容器之间的连接,ovs的连接,多食用veth-pair

两个容器之间通讯。类似这样;

image-20210914155955316

结论:tomcat01 和tomcat02 共用一个路由器,docker0

所有的容器不指定网络的情况下,都是docker0路由的,docker会给我们的容器分配一个默认的可用ip

小结

docker使用的是linux的桥接,宿主机中是一个docker容器的网桥docker0

image-20210914160305122

docker 中的所有网络接口都是虚拟的。虚拟的转发效率高???

只要删除容器,对应网桥一对就没了。

docker run -d -P --name tomcat01 selftomcat

docker run -d -P --name tomcat02 selftomcat
[root@ip-172-31-43-53 tomcat]# docker exec  -it tomcat02 ping tomcat01
ping: tomcat01: Name or service not known


docker run -d -P --name tomcat03 --link tomcat01 selftomcat

[root@ip-172-31-43-53 tomcat]# docker exec -it tomcat03 ping tomcat01
PING tomcat01 (172.17.0.2) 56(84) bytes of data.
64 bytes from tomcat01 (172.17.0.2): icmp_seq=1 ttl=64 time=0.077 ms
^C
--- tomcat01 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.077/0.077/0.077/0.000 ms

# 正向的连接可以,反向的连接不可以,配置反向之后就可以了;
# 配置容器的hosts文件就可以了。

–link其实就是在hosts文件中增加了对应的解析;

目前我们在使用docker已经不建议使用–link了

自定义网络。不实用于docker0

docker0问题:他不支持容器名连接访问。

自定义网络

查看所有的docker网络

image-20210914173503978

网络模式

Bridge:桥接 docker(默认,自己创建也使用 bridge 模式)

none:不配置网络

host:和宿主机共享网络

container:容器网络连通!(用的少!局限很大)

测试

# 我们直接启动的命令 -net bridge,而这个就是我们的docker0  
docker run -d -P --name tomcatol --net bridge tomcat

# docker0 特点,默认,域名不能访问,--link可以打通连接。

# 自己定义一个网络
[root@ip-172-31-43-53 tomcat]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
9cb18bce7306ab3d0ad9ccf49cc051da17e0636874b8997fd5a313cd70ec594a
[root@ip-172-31-43-53 tomcat]# docker network ls
NETWORK ID     NAME          DRIVER    SCOPE
8c856f6d4467   bridge        bridge    local
3b79f3f688c8   host          host      local
9cb18bce7306   mynet         bridge    local
3aba1cb2609f   none          null      local
7dac22c97724   somenetwork   bridge    local

自己创建的网络信息

image-20210914175255256

启动容器

[root@ip-172-31-43-53 tomcat]# docker run -d -P --name tomcat-mynet01 --network mynet selftomcat
93e9d3054c6ec9cc0f0aeb82a8c37da120e40d823ac196a409d92718c26a9939

查看信息

image-20210914175446404

优点

  • 自定义网络docker已经帮我们维护好了对应的关系,直接可以ping通
  • 不同的集群使用不同的网络,保证集群是安全

网络连通

image-20210914180031906

连接一个容器到一个网络

测试tomcat01 联通mynet网络

image-20210914180357020

[root@ip-172-31-43-53 tomcat]# docker network connect mynet tomcat01
[root@ip-172-31-43-53 tomcat]# docker inspect mynet

image-20210914180245851

直接将 tomcat01 写入到 mynet 网络中了

一个容器两个ip

[root@ip-172-31-43-53 tomcat]# docker exec  -it tomcat01 ping tomcat-mynet01
PING tomcat-mynet01 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat-mynet01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.053 ms
64 bytes from tomcat-mynet01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.050 ms
^C
--- tomcat-mynet01 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 0.050/0.051/0.053/0.007 ms

实战:部署redis集群

image-20210914181232159
# 创建网卡
[root@ip-172-31-43-53 ~]# docker network create redis --subnet 172.38.0.0/16
cf8ac01f699efc0ef552c1d8ad4d74762745679264f3dbf506117549572da437

# 通过脚本创建配置
for port in $(seq 1 6);
do
mkdir -p /data/redis/node-${port}/conf
touch /data/redis/node-${port}/conf/redis.conf
cat << EOF > /data/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
docker run -p 637${port}:6379 -p 1637${port}:16379 --name redis-${port} \
-v /data/redis/node-${port}/data:/data \
-v /data/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

# 随便登陆其中一个redis,创建集群,并且启动分片
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

# 等到创建完毕之后可以登陆redis cluster
/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:189
cluster_stats_messages_pong_sent:183
cluster_stats_messages_sent:372
cluster_stats_messages_ping_received:178
cluster_stats_messages_pong_received:189
cluster_stats_messages_meet_received:5
cluster_stats_messages_received:372

# 可以看到,集群是三个节点,
127.0.0.1:6379> CLUSTER NODES
c0ff2fcf4ef53d94b131e846ba21fe12da4bdfea 172.38.0.12:6379@16379 master - 0 1631690115000 2 connected 5461-10922
3c9261534107e331705d44245b196651c71aa0a8 172.38.0.11:6379@16379 myself,master - 0 1631690114000 1 connected 0-5460
c2e0fe45571f851cd79a5a09ac3799f670105ae0 172.38.0.13:6379@16379 master - 0 1631690115114 3 connected 10923-16383
4a690ba44ab53e0bdd2ed85b6796796df4c2b9e5 172.38.0.15:6379@16379 slave 3c9261534107e331705d44245b196651c71aa0a8 0 1631690113512 5 connected
a8553424b03677c306cc9d308d03de4ea0c17956 172.38.0.14:6379@16379 slave c2e0fe45571f851cd79a5a09ac3799f670105ae0 0 1631690114112 4 connected
a89526668e41cec41a7484cc4f909a3c2bf96bc5 172.38.0.16:6379@16379 slave c0ff2fcf4ef53d94b131e846ba21fe12da4bdfea 0 1631690115515 6 connected
127.0.0.1:6379>

# 可以看到三主三从

posted @ 2021-09-15 15:23  Star-Hitian  阅读(190)  评论(0)    收藏  举报