Docker

Docker基本概念

Docker的基本组成

1.镜像(image)

Docker 镜像(Image)就是一个只读的模板,当于是一个root文件系统,也相当于容器的“源代码。
镜像是轻量级可执行的独立软件包,它包含运行某个软件所需要的所有内容,包括代码,运行时库,环境变量和配置文件

2.容器(container)

1 从面向对象角度
容器就类似于一个虚拟化的运行环境,容器是用镜像创建的运行实例。
镜像是静态的定义,容器是镜像运行时的实体。
容器为镜像提供了一个标准的和隔离的运行环境,它可以被启动、开始、停止、删除。
每个容器都是相互隔离的、保证安全的平台

2 从镜像容器角度
可以把容器看做是一个简易版的 Linux 环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。

3.仓库(Repository)

是集中存放镜像文件的场所。
仓库分为公开仓库(Public)和私有仓库(Private)两种形式。
最大的公开仓库是 Docker Hub(https://hub.docker.com/),
存放了数量庞大的镜像供用户下载。国内的公开仓库包括阿里云 、网易云等

·

Docker工作原理

Docker 是一个 C/S 模式的架构,后端是一个松耦合架构,众多模块各司其职。Docker守护进程运行在主机上,然后通过Socket连接从客户端访问,守护进程从客户端接收命令并管理运行在主机上的容器
在这里插入图片描述

docker运行的基本流程为
1.用户使用docker client 与docker deamon建立通信,并发送请求给后者
2.docker daemon作为docker架构中的主体部分,首先提供docker server的功能使其可以接收docker client的请求
3.docker engine指定docker内部的一系列工作,每一项工作都是以一个job的形式的存在
4.job的运行过程中,当需要容器镜像时,则从docker registry中下载镜像,并通过镜像管理驱动graph driver将下载镜像以Graph的形式存储。
5.当需要为docker创建网络环境时,通过网络管理驱动NetWork driver创建并配置docker容器网络环境
6.当需要限制docker容器运行资源或执行用户指令等操作时,则通过exec driver来完成
7.libcontainer时一项独立的容器管理包,network driver以及exec driver都是通过libcontainer来实现具体对容器进行的操作

在这里插入图片描述

镜像加载原理

UnionFS联合文件系统

UFS是一种分层、轻量级并且高性能的文件系统,支持对文件系统的修改作为一次提交来一层层叠加,同时可以将不同目录挂载到同一个虚拟文件系统下,docker镜像可以通过分层来进行继承,基于基础镜像可以制作各种具体的应用镜像

加载原理

bootfs:主要包含bootloader和kernel,bootloader主要是引导加载kernel,linux刚启动会加载bootfs文件系统,在docker最底层是bootfs,这一层与我们典型的linux系统是一样的,包含boot加载器和内核,当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。(意思是当linux启动后,容器的启动都是直接建立在linux机的bootfs之上,所有容器的启动不再单独再次运行bootfs,而是用linux机的?)

rootfs:在bootfs之上。是各种不同操作系统的标准发行版本,如centos

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

镜像就相当于能调用底层linux的东西都去使用它,比如bootfs,只加载必要的rootfs和其他,因此精简

分层原理

分层结构最大的好处就是资源共享,

所有docker镜像都起源于一个基础镜像层,当进行修改或增加新内容时,就会在当前镜像层上创建新的镜像层

在添加额外的镜像层的同时,镜像始终保持是当前所有镜像的组合

docker通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统。

docker镜像都是只读的,当容器启动的时候,一个新的可写层被加载到镜像的顶部,即基础下载的镜像是不会改变的,当我们运行的容器都是可以修改的容器层+不可修改的镜像层,对外发布可以将这两个打包成一个整体的镜像

为什么docker比虚拟机更快

(1)docker有着比虚拟机更少的抽象层
由于docker不需要Hypervisor(虚拟机)实现硬件资源虚拟化,运行在docker容器上的程序直接使用的都是实际物理机的硬件资源。因此在CPU、内存利用率上docker将会在效率上有明显优势。
(2)docker利用的是宿主机的内核,而不需要加载操作系统OS内核
当新建一个容器时,docker不需要和虚拟机一样重新加载一个操作系统内核。进而避免引寻、加载操作系统内核返回等比较费时费资源的过程,当新建一个虚拟机时,虚拟机软件需要加载OS,返回新建过程是分钟级别的。而docker由于直接利用宿主机的操作系统,则省略了返回过程,因此新建一个docker容器只需要几秒钟。

在这里插入图片描述

安装部署

yum安装

1.卸载旧版本docker

sudo yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine

3.yum 安装gcc相关

yum -y install gcc
yum -y install gcc-c++ 

4.安装需要的软件包

sudo yum install -y yum-utils

5.设置stable镜像仓库

#官网上的地址是国外的,非常慢,是个坑,一般需要换到国内的替代地址
#经常会报TCP链接重置或者连接超时的错误
#sudo 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

6.更新yum软件包索引

yum makecache fast

7.安装docker ce

sudo yum install docker-ce docker-ce-cli containerd.io docker-compose-plugin

8.启动docker

systemcl start docker

#测试是否正常
docker version

9.卸载docker

systemctl stop docker
yum remove docker-ce docker-ce-cli contaninerd.io docker-compose-plugin
rm -rf /var/lib/docker
rm -rf /var/lib/containerd

Docker配置

配置阿里云镜像

首先注册阿里云账户,注册容器镜像服务,生成自己的阿里云镜像地址

sudo mkdir -p /etc/docker
# 将EOF前面的内容反写进入deamon.json
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://dwi14745.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

本地包部署

1.下载包
https://download.docker.com/linux/static/stable/x86_64/

# 1.下载包
https://download.docker.com/linux/static/stable/x86_64/

# 2.解压包
tar -zxvf docker-19.03.9.tgz

# 3.复制所有文件到/usr/bin
cp docker/* /usr/bin/

# 4.配置docker,service添加配置内容
vim /etc/systemd/system/docker.service

[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target

[Service]
Type=notify
ExecStart=/usr/bin/dockerd
ExecReload=/bin/kill -s HUP $MAINPID
LimitNOFILE=infinity
LimitNPROC=infinity
TimeoutStartSec=0
Delegate=yes
KillMode=process
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s

[Install]
WantedBy=multi-user.target

# 5.给执行权限
chmod +x /etc/systemd/system/docker.service

# 6. 设置daemon-reload
systemctl daemon-reload

# 7.启动docker
systemctl start docker

修改docker默认存储路径

docker默认将/var/lib/docker作为存储路径,若要调整,如下

#1.创建daemon.json配置文件,默认没有这个文件,需要添加
vim /etc/docker/daemon.json
# 添加如下
{
  "data-root": "/data"
}

# 保存后重启服务
systemctl restart docker

# 查看是否调整成功
docker info

Docker常用命令

帮助启动命令

#启动docker
systemctl start docker
#停止docker
systemctl stop docker
#重启docker
systemctl restart docker
#查看docker状态
systemctl status docker
#开机启动
systemctl enable docker

#查看docker版本,可验证是否安装docker成功
docker version

#系统信息
docker info

#所有命令,详细信息还可以查看官方文档
docker --help

#查看所有服务
docker service ls

镜像命令

#查看已经下载的镜像
docker images
#从官方库搜索镜像
docker search xxx
#下载镜像
docker pull xxx[:TAG]
#查看镜像/容器/数据卷所占用的空间
docker system df xxx
#删除某个镜像
docker rmi xxx
#删除全部
docker rmi -f $(docker iamges -qa)

#将镜像达成tar包
docker save [镜像id]>./xxx.tar
#加载本地镜像
docker load < xxx.tar

# 修改镜像
docker tag ubuntu:latest myubuntu:latest

容器命令

#查看dockers下容器所占用的内存与cpu情况
docker stats xxx
#查看容器日志
docker logs [容器名/容器id]
#设置容器自启动
docker update [容器id] --reastart=always
#将容器内的目录复制到当前路径, 录入nginx
docker container cp nginx:/etc/nginx


#交互形式进入容器内部,exec退出容器终端不会导致容器停止
# 通过attach也可以进入容器内部,但是退出会导致容器停止,不建议用
docker exec -it [容器id]

# 查看容器中文件结构的更改
docker diff [id]

# 查看端口映射
docker port [id]

#查看容器配置信息
docker inspect [容器id]

#查看所有节点,只显示id,hostname,addr,state
docker inspect $(docker node ls -q) --format='{{.ID}}  {{.Description.Hostname}} {{.Status.Addr}}   {{.Status.State}} '

#查看容器进程
docker top [id]

将镜像启动成容器

#一、新建容器:docker [container] create
	#--name="name" 容器名字
	#-d	后台运行方式
	#-it	使用交互方式运行
	#-p	指定容器的端口
		#-p ip:主机端口:容器端口
		#-p 主机端口:容器端口【常用】
		#-p 容器端口
	#-P	随机指定端口
	#-e	传递环境变量
docker create -it ubuntu:latest//新建的容器处于停止状态,需要启动
#启动容器(根据容器ID启动)
docker start 容器id

#二、新建容器并启动
# docker [container] run
	#-d:指后台运行
	#-p:指定端口映射先写外部端口再写内部端口
	#--name:指定容器运行起来后的名字
	#-v:可以映射文件,用途很广,比如可以将当前目录映射到/usr/share/nginx/html	
	#-i:以交互模式运行容器,通常与 -t 同时使用
	#-t:为容器重新分配一个伪输入终端,通常与 -i 同时使用
	#-e:设置环境变量
#当利用run创建启动容器时,docker在后台的标准操作
	#1.检查本地是否存在指定的镜像,不存在就从共有仓库下
	#2.利用镜像创建一个容器,并启动该容器
	#3.分配一个文件系统给容器,并在只读的镜像层外挂载一层可读写层
	#4.从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中去
	#5.从网桥的地址池配置一个IP地址给容器
	#6.执行用户指定的应用程序
	#7.执行完毕后容器被自动终止


#对于创建的bash容器,当用户使用exit退出bash进程后,容器也会自动退出,这是因为当其中应用退出后,容器的使命完成,也就没有继续运行的必要了,下面会启动并进入容器
docker run -it ubuntu:18.04 /bin/bash  //指定运行bash应用,不会运行其他无关进程

#'pwd'指当前目录, 将当前目录映射到指令目录,这样可以将一些静态文件放在外面,在外面修改文件(因为是映射 的)里面的文件就会跟着变化,这个映射还会用于其他一些数据的保存,比如mysql的data目录也可以映射到外面,防止数据丢失,最后需要接的参数是镜像的名字,如果有具体的版本最好不要省略,省略就是latest最新版,如果镜像一直在全新的构建的话,latest会不断更新,如果有一个正在使用的稳定版本,可以指定到这个版本吧
docker run -d -p 88:80 --name mynginx -v 'pwd' :/usr/share/nginx/html nginx:1.13

#当docker run 时无法正常执行容器而出错退出,可以查看退出的错误代码
	# 125:docker deamon执行出错,例如指定了不支持的docker命令参数
	# 126:指定命令无法执行,例如权限出错
	# 127:容器内命令无法找到


#三、守护态运行,使用该后台运行就必须需要有一个前台进程,docker发现没有应用就会自动停止
docker run -d ubuntu /bin/sh
#以后台运行的方式启动,并且把容器外的3355端口和容器内的8080端口做映射
docker run -d -p 3355:8080 --name tomcat1 tomcat

#启动容器,并且通过-e设置单点分布,以及容器的最大占用内存,以es为例
docker run -d --name es1 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.6.2

停止容器

#一、暂停容器:docker pause 
#处于paused状态的容器,可以用docker unpause回复到运行
docker pause test

#二、终止容器:docker stop
#该命令会首先想容器发送SIGTERM信号,默认等待10秒后,再发送SIGKILL信号来终止容器
#还可以通过docker kill 直接发送SIGKILL信号来强行终止容器
docker stop 容器id
#强制停止当前容器
docker kill 容器id
#直接停止容器并退出
exit
#容器不停止退出
Ctrl + P + Q

#三、重启容器:docker restart
#该命令会将一个运行的容器先终止再重新启动
docker restart b27a32

操作容器

#1.attach,进入容器正在执行的终端,不会启动新的进程
#多个窗口同时attach到一个容器时,所有窗口都会同步显示,当某个窗口因命令阻塞时,其他窗口也无法操作
# 退出容器后容器将停止,不建议使用该命令,多用exec
docker attach xxx

#2.exec,进入容器后开启一个新的终端,可以在里面操作
docker exec -it b27a32 /bin/bash

#3.本地路径的data复制到test容器的/tmp路径下
docker [container] cp data test:/tmp/

#查看统计信息,cpu状态
docker stats [id]

#查看日志
docker logs -f -t --tail [id]



删除容器

#docker [container] rm
	#-f:是否强行终止并删除一个运行的容器
	#-l:删除容器的连接,但保留容器
	#-v:删除容器挂载的数据卷
#默认下docker rm只能删除已经处于终止或退出状态的容器,并不能删除运行中的容器
#如果要删除运行中的容器,可以添加-f参数,docker会先发送SIGKILL信号,终止其中应用,之后强行删除
docker rm b27a32
docker ps -a -q|xargs docker rm //通过管道符删除所有容器


#更新配置
#限制总配额为1秒,容器所占用时间为10%
docker update --cpu-quota 1000000 b27a32
docker update --cpu-period 100000 b27a32

将容器提交成为镜像

docker镜像都是只读的,当容器启动的时候,一个新的可写层被加载到镜像的顶部,即基础下载的镜像是不会改变的,当我们运行的容器都是可以修改的容器层+不可修改的镜像层,对外发布可以将这两个打包成一个整体的镜像

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

导入和导出容器

导出后的tar文件可传输到其他机器上,然后再通过导入命令导入到系统中,实现容器的迁移

使用import将丢弃所有历史记录和元数据信息,但可以重新指定标签等元数据信息

镜像中的docker load也可以导入,存储的文件保存记录完整,体积更大

//1.导出容器,指导出一个已经创建的容器到一个文件,不管此时这个容器的状态
//将容器id ce5开头的导出到test1.tar
docker export -o test1.tar ce5
//将容器id e81开头的导出到test2.tar
docker export e81 >test2.tar

//将镜像打包
docker save xxx >./test.war

//2.导入容器
docker import test2.tar - test/ubuntu:1.0

集群相关

#生成集群绑定命令
#复制该命令在其他从服务器中执行即可添加集群,使用portainer的话可以在swarm下看到主机的ip,节点信息
docke swarm join-token worker

#强制脱离集群
docker swarm leabe --force

仓库命令

#1 登录私库
docker login registry.xxx.com:5000 -u demo -p xxx

# 2pull镜像
docker pull registry.xxx.com:5000/demo/xxx-ui:20220510
# 3给镜像重新打标签
docker tag registry.xxx.com:5000/demo/xxx-ui:20220510 192.168.35.43:5000/xxx-ui:20220510

# 4将镜像上传到本地仓库
docker push  192.168.35.43:5000/xxx-ui:20220510

镜像分层概念

什么是镜像

镜像是轻量级,可执行的独立软件包,包含运行某个软件所需要的所有内容,我们把应用程序和配置依赖打包好形成一个可交付的运行环境(包括代码,运行时需要的库,环境变量和配置文件等),这个打包好的环境就是镜像

分层的镜像

UnionFS(联合文件系统)

Union是一种分层,轻量级并且高性能的文件系统,支持对文件系统的修改作为一次提交来一层层叠加,同时可以将不同目录挂载到同一个虚拟文件系统下
Union是docker镜像的基础,镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像

特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来

docker镜像加载原理

为什么docker镜像采用分层结构

容器卷

docker 容器中产生的数据可以同步到本地,这就是卷技术,可视为目录的挂载,将容器的目录挂载到linux上
通过容器数据卷技术可以对容器进行持久化和同步的操作,容器间也是可以数据共享的

DockerFile

dockerFile简介

dockerfile是构建docker镜像的文本文件,是由一条条构建镜像所需的指令和参数构成的脚本

构建三部曲

1.编写Dockerfile文件
2.docker build命令构建镜像
3.docker run 依镜像运行容器实例

dockerfile构建过程解析

1.每条保留字指令要求大写,且后面跟随至少一个参数
2.指令从上到下依次执行
3. #表示注释
4. 每条执行都会创建一个新的镜像层并对镜像进行提交

dockerfile常用保留字指令

在这里插入图片描述

FROM
基础镜像,当前新镜像是基于哪镜像,制定一个已经存在的镜像作为模板,dockerfile第一条指令必须是FROM
MAINTAINER
镜像维护者的姓名和邮箱地址
RUN
容器构建时需要运行的命令,分为shell格式和exec模式
RUN在docker build时运行

# shell格式
# <命令行命令>等同于,在终端操作的shell命令
RUN <命令行命令>

# 示例,下方命令在build的时候就会执行
RUN yum -y install vim
# exec模式
RUN ["可执行文件","参数1","参数2"]

#示例,等价于RUN ./test.php dev offline
RUN ["./test.php","dev","offline"]

EXPOSE
当前容器对外暴露的端口

WORKDIR
指定在容器创建后,终端默认登录进来的工作目录,一个落脚点
USER
指定该镜像以什么用户去执行,如果都不指定,默认是root
ENV
用来在构建镜像过程中设置环境变量

#这个环境变量可以在后续的任何RUN指令中使用,如果在命令前指定了环境变量前缀一一样
#也可以在其他指令中直接使用这个环境变量
ENV MY_PATH /usr/mytest

#使用示例
WORKDIR $MY_PATH

ADD
将宿主机目录下的文件拷贝进镜像且会自动处理URL和解压tar压缩包,和COPY类似,相当于COPY+解压

COPY
docker中也有cp命令 docker cp 容器ID:容器内路径 目的主机路径,COPY的作用类似
COPY也类似ADD,用于拷贝文件和目录到镜像中
将从构建上下文目录中<源路径>的文件 / 目录复制到新的一层的镜像内的<目标路径>

VOLUME
容器数据卷,用于数据保存和持久化工作
CMD
指定容器启动后需要干的事情
CMD指定的格式和RUN相似,也是两种格式,shell和exec
CMD在docker run时运行,RUN在docker build时运行
Dockerfile可以有多个CMD指令,但只有最后一个生效,CMD会被docker run之后的参数替换

EXPOSE 8080
#启动tomcat
CMD ["catalina.sh","run"]

#该命令会正常调用CMD的设置启动tomcat暴露8080
docker run -it -p 8080:8080 30ef 

# 该命令相当于会在CMD后面再加一行 CMD ["/bin/bash","run"]
# 则只有最后一行CMD生效,所以容器运行,会进入/bin/bash路径,但是不会启动tomcat,8080无法访问
docker run -it -p 8080:8080 30ef /bin/bash

ENTRYPOINT
也用于指定一个容器启动时要运行的命令
类似CMD,但不会被docker run后面的命令覆盖,而且这些命令行参数会被当作参数送给ENTRYPOINT指令指定的程序

命令格式: ENTRYPOINT ["<executeable>","<param1>","<param2>"...]
ENTRYPOINT可以和CMD一起,一般是变参才会使用CMD,这里的CMD等于是在给ENTRYPOINT传参
当指定了ENTRYPOINT后,CMD的含义就发生了变化,不再直接运行其命令而是将CMD的内容作为参数传递给ENTRYPOINT指令,组合变成<ENTRYPOINT> "<CMD>"

#假设已经通过dockerfile构建了nginx:test镜像
FROM nginx
ENTRYPOINT ["nginx","-c"] #定参
CMD ["/etc/nginx/nginx.conf"] #变参

是否传参按照dockerfile编写执行传参运行
Docker命令docker run nginx:testdocker run nginx:test -c /etc/nginx/new.conf
衍生出的实际命令nginx -c /etc/nginx/nginx.confnginx -c /etc/nginx/new.conf

案例

自定义mycentosjava8镜像

# 前置条件:本地已经下载了centos镜像
# 要求:镜像具备 vim+ifconfig+jdk8
# 要求:本地环境有jdk8包: jdk-8u171-linux-x64.tar.gz
# java8下载地址 :https://www.oracle.com/java/technologies/downloads/#java8

vim Dockerfile
--------------------------------------------------------------------------
FROM centos
MAINTAINER hhxx<hhxx@qq.com>

ENV MY_PATH /user/local
WORKDIR $MY_PATH

RUN yum -y intall vim

RUN yum -y install net-tools

RUN yum -y install glibc.i686
# ADD的jdk包要和Dockerfile在同一位置
ADD jdk-8u171-linux-x64.tar.gz /usr/local/java/

ENV JAVA_HOME /usr/local/java/jdk1.8.0_171
ENV JRE_HOME $JAVA_HOME/jre
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib:$CLASSPATH
ENV PATH $JAVA_HOME/bin:$PATH

EXPORSE 80 
CMD echo $MYPATH
CMD echo "success ok"
CMD /bin/bash
------------------------------------------------------------------------------


# 构建,不要忘记最后的.
docker build -t centosjdk8:1.0 .

总结

dockerfile,docker镜像和docker容器分别代表软件的三个阶段
在这里插入图片描述

dockerfile

dockerfile是软件的原材料,面向开发
镜像反解析后对应的一个个文件就是dockerfile
dockerfile定义了进程需要的一切东西,dockerfile涉及的内容包括执行的代码或者是文件、环境变量、依赖包、运行时环境、动态链接库,操作系统的发行版本,服务进程和内核进程(当应用进程需要和系统服务和内核进程打交道,这时需要考虑如何设计namespace的权限控制)

docker镜像

docker镜像是软件的交付品,交付标准

docker容器

docker容器则是软件的运行状态,直接提供服务,涉及部署和运维

虚悬镜像

仓库名和标签名都是的镜像,不能用

#测试构建虚悬镜像

# 1. vim Dockerfile

form centos
CMD "success"

# 2.build构建,就会生成
docker build . 


# 查看系统所有的虚悬镜像
docker image ls -f dangling=true

# 删除所有的虚悬镜像
docker image prune

Docker微服务实战

1.通过idea新建一个普通微服务模块

xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.8.RELEASE</version>
        <relativePath/>
    </parent>
    <groupId>org.example</groupId>
    <artifactId>docker_boot</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <junit.version>4.12</junit.version>
        <log4j.version>1.2.17</log4j.version>
        <lombok.version>1.16.18</lombok.version>
        <mysql.version>5.1.47</mysql.version>
        <druid.version>1.1.16</druid.version>
        <mybatis.spring.boot.version>1.3.0</mybatis.spring.boot.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

yml

server:
  port: 6001

启动类

package com.huaxin.docker;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DockerBootApplication {
    public static void main(String[] args) {
        SpringApplication.run(DockerBootApplication.class,args);
    }
}

controller

package com.huaxin.docker.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.UUID;
@RestController
public class OrderController {
    @Value("${server.port}")
    private String port;
    @RequestMapping("/order/docker")
    public String helloDocker(){
        return "hello,docker"+"\t"+port+"\t"+ UUID.randomUUID().toString();
    }
    @RequestMapping(value = "/order/index",method = RequestMethod.GET)
    public String index(){
        return "服务端口号"+"\t" +port+"\t"+UUID.randomUUID().toString();
    }
}

最后通过maven的package打出jar包

通过dockerfile发布微服务部署到docker容器

#1.在linux环境机器创建测试目录,例如/mydocker
#2.将jar包上传到该目录
#3.在该目录下 vim Dockerfile
-----------------------------------------------------------------------------
#基础镜像使用java
FROM java:8
#作者
MAINTAINER huaxin
#指定临时文件目录为/tmp,在主机/var/lib/docker目录下创建了一个临时文件并链接到容器的/tmp
VOLUME /tmp
#将jar包添加到容器内并改名
ADD docker_boot-1.0-SNAPSHOT.jar huaxin_docker.jar
#运行jar包
RUN bash -c 'touch /huaxin_docker.jar'
ENTRYPOINT ["java","-jar","/huaxin_docker.jar"]
#暴露端口
EXPOSE 6001
-----------------------------------------------------------------------------

#4. build出镜像
docker build -t huaxin_docker:1.1 .

#5. 启动镜像
docker run -d -p 6001:6001 3db

#6.测试
curl http://1.12.249.69:6001/order/index

Docker网络

是什么

docker 不启动时,linux的网络情况

通过ifconfig 或ipaddr可以查看网络

ens33
lo

virbr0
在centos7的安装过程中如果有选择相关虚拟化的服务安装系统后【例如linux图形化桌面,就要支持虚拟化服务】,启动网卡时会发现有一个以网桥连接的私网地址的virbr0网卡(virbr0网卡:它还有一个固定的默认IP地址192.168.122.1),是做虚拟机网桥使用的,作用是为连接其他虚拟网卡,提供NET访问外网的功能

linux安装,勾选安装系统时附带了libvirt服务才会生成这个东西,不需要可以yum remove libvirt-libs.x86_64卸载

docker启动后的网络状态

启动docker后会产生一个名为docker0的虚拟网桥
docker服务默认会创建这个docker0网桥(其上有一个docker0内部接口),该桥接网络的名称为docker0,它在内核层联通了其他的物理或虚拟网卡,这就将所有容器和本地主机都放到同一个物理网络,docker默认指定了Docker0接口的IP地址和子网掩码,让主机和容器之间可以通过网桥相互通信
在这里插入图片描述

docker默认下的网络
docker默认创建三大网络模式,主要用bridge,勉强用host,一般不用none

常用基本命令

#通过下命令可以查看docker默认网络[安装后没有修改时的状态]
#docker network [command]
#commands
#	connect :连接
#	create	:创建
#	disconnect	:中断
#	inspect	:查看详细
#	ls	:查看
#	prune	:删除所有无效,不占用的网络
#	rm	:删除指定网络 
docker network ls


NETWORK ID     NAME      DRIVER    SCOPE
bd6d0f8add85   bridge    bridge    local
662a75feca6a   host      host      local
72c38821ee62   none      null      local

能干啥

容器间的互联通信以及端口映射
容器IP变动时候可以通过服务名直接网络通信而不受到影响
docker网络管理和容器调用之间的规划

网络模式

网络模式详细分类

网络模式简介
bridge为每个容器分配,设置IP等,并将容器连接到一个docker0虚拟网桥,默认为该模式
使用 --network bridge指定,默认docker0
host容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口
使用 --network host指定
none容器有独立的Network namespace,但并没有对其进行任何网络设置,如分配veth pair和网络桥接,IP等
使用 --network none指定
container新创建的容器不会创建自己网卡和配置自己的IP,而是和一个指定的容器共享IP,端口范围等
使用 --network container:NAME或容器ID指定
自定义网络自定义网络实现了通过容器名ping通,更适合容器集群之间的通信

容器示例内默认网络IP生产规则

docker容器内部的ip是可能发生改变的
例如启动了镜像 centos 生成容器centos01,和centos02
假设此时centos01网络为172.17.0.2,centos02网络为172.17.0.3
如果centos02停止,或删除,02的网络就停止了
此时再启动centos03,03的网络可能还为172.17.0.3
若centos01原来与centos02通信,02单机,03起来后,就变为和03通信了,即网络发生变化,导致通信错误

容器通信的重要前提:ip地址发生变化不能影响调用通信出问题,且希望调用的服务号处于同一网段

bridge

#查看bridge网络的详细信息,并通过grep获取名称项
docker network inspect bridge | grep name

bridge解析

1.Docker使用linux桥接,在宿主机虚拟一个docker容器网桥(docker0),docker启动一个容器时会根据docker网桥的网段分配给容器一个IP地址,成为Container-IP,同时Docker网桥是每个容器的默认网关,因为在一宿主机内的容器都接入同一个网桥,这样容器之前就能够通过容器的Container-IP直接通信


2.doker run的时候,没有指定network的话默认使用的网桥模式就是bridge,使用的就是docker0,在宿主机ip addr就可以看到docker0和自己create的network eth0,eth1,eth2…代表网卡1,2,3… lo达代表127.0.0.1,inet addr用来表示网卡的IP地址


3.网桥docker0创建一对对等虚拟设备接口一个叫veth,另一个叫eth0,成对存在与匹配
  整个宿主机的网桥模式都是docker0,类似一个交换机有一堆接口,每个接口叫veth,在本地主机和容器内分别创建一个虚拟接口,并让他们彼此联通(这样一对接口叫veth pair)
  每个容器示例内部也有一块网卡,每个接口叫eth0
  docker0上面的每个veth匹配某个容器实例内部的eth0,两两匹配,一一对应


综上所述,将宿主机上的所有容器都连接到这个内部网络上,两个容器在同一网络下,会从这个网关下各自拿到分配的ip,此时两个容器的网络是互通的

在这里插入图片描述

在这里插入图片描述

host

直接使用宿主机的IP地址与外界进行通信,不再需要额外进行NAT转换
容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace,容器将不会虚拟出自己的网卡而是使用宿主机的IP和端口


该方式docker启动时指定–network=host或-net=host,此时-p参数不会有任何作,端口号会以主机端口号为主,重复则递增
类似虚拟机的桥接模式
在这里插入图片描述

none

禁用了网络功能,只有lo标识(就是127.0.0.1表示本地回环)
在none模式下,不为docker容器进行任何网络配置,即这个docker容器没有网卡,IP,路由等信息,只有一个lo
需要我们自己为docker容器添加网卡,配置IP等

container

新建的容器和已经存在的一个容器共享一个网络ip配置而不是和宿主机共享,新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP,端口范围等,同样,两个容器除了网络方面,其他的如文件系统,进程列表等还是隔离的
在这里插入图片描述

在这里插入图片描述

自定义网络模式

自定义网络存在的问题

默认网络模式可以通过ip互ping,但是无法通过容器名ping,并且当某一容器宕机后,后增加的容器可能会顶替之前宕机的容器的ip,导致容器间通讯混乱,自定义网络解决了这个问题,通过容器名可以Ping实现了容器通信的唯一性,并且可以自由的根据业务设置网络通信模式

docker多个容器之间的集群规划一定要用服务名通信而不是ip

自定义网络案例

自定义网络默认使用桥接网络bridge

#新建自定义网络
docker network create huaxin_net

#新建容器加入自定义网络
docker run -d -p 8081:8080 --network huaxin_net --name tomcat81 billygoo/tomcat8-jdk8
docker run -d -p 8082:8080 --network huaxin_net --name tomcat82 billygoo/tomcat8-jdk8

Docker 平台架构图

整体说明

Docker是一个C/S模式的架构,后端是一个松耦合架构,众多模块各司其职

Docker的运行流程为:
1.用户使用docker client和docker daemon建立通信,并发送请求给后者
2.docker daemon作为docker 架构中的主体部分,首先提供docker server 的功能使其可以接受docker client的请求
3.docker engine执行docker 内部的一系列工作,每一项工作都是以一个job的形式存在
4.job的运行过程中,当需要容器镜像时,则从Docker registry中下载镜像,并通过镜像管理驱动Graph driver将下载镜像以Graph的形式存储
5.当需要为docker创建网络环境时,通过网络管理驱动Network driver 创建并配置docker 容器网络环境
6.当需要限制docker容器运行资源或执行用户指令等操作时,通过Execdriver来完成
7.Libcontainer是一项独立的容器管理包,Network driver以及Exec driver都是通过Libcontainer来实现具体对容器进行的操作

整体架构
在这里插入图片描述

Docker Compose

核心概念

docker compose是docker官方的开源项目,负责实现对docker容器集群的快速编排,可以管理多个docker容器组成一个应用
需要定义一个yaml格式的配置文件docker-compose.yml,写好多个容器之间的调用关系,然后一个命令可以同时启动或关闭这些容器
docker-compose是单机的多容器管理技术,k8s是跨主机的集群部署工具

核心要素:服务和工程

服务
指一个个应用容器实例

工程
一组关联的应用容器组成的一个完整业务单元,在docker-compose.yml文件中定义

安装

官网有两个版本version2和version3,尽量使用version3(需要和docker版本引擎匹配,1.13.0++)
在这里插入图片描述

安装流程
github连接不上可以百度找国内网站替代在这里插入图片描述

使用步骤

在这里插入图片描述

常用命令

在这里插入图片描述

docker-compose案例

sql建表

CREATE TABLE `t_user`(
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL DEFAULT '' COMMENT '用户名',
`password` varchar(50) NOT NULL DEFAULT '' COMMENT '密码',
`sex` tinyint(4) NOT NULL DEFAULT '0' COMMENT '性别 0=女 1=男',
'deleted' tinyint(4) unsigned NOT NULL DEFAULT '0' COMMENT '删除标志,默认0不删除,1删除',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON CURRENT_TIMESTAMP COMMENT '更新时间',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`id`)
)ENGINE=INNODB AUTO_INCREMENT=1114 DEFAULT CHARSET=utf8 COMMENT='用户表'

Portainer

#安装
docker run -d -p 18000:8000 -p 19000:9000 --name portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer

Docker Swarm

运维案例

修改了挂载的配置文件然后启动报错

#进入了mysql容器内部
docker exec -it 213 /bin/bash
#修改了配置文件 ,然后重启发现报错
vim /ect/mysql/conf/mysql.cnf

#查看docker配置文件信息
docker inspect 213

#找到GraphDriver.Data.MergedDir这个属性,并且进入到地址
cd /var/snap/docker/common/var-lib-docker/overlay2/xxxxxxxxxxxxxxx
#在进入到配置文件地址
cd diff/etc/mysql/mysql.cnf
#修改好配置文件后重新启动

porainer更新为https服务

1.下载最新的portainer-ce

docker pull portainer/portainer-ce:latest

2.没有私库的情况下,tag镜像为非latest
解决启动一直去拉取最新镜像导致启动不起来的问题
在这里插入图片描述

docker  tag portainer/portainer-ce:latest portainer/portainer-ce:1.0

注意:agent和私库需要一样的操作
在这里插入图片描述
3. 修改portainer-agent-stack.yml文件
一般在/opt/install-portainer/ 文件夹下
在这里插入图片描述
4.在portainer-agent-stack.yml所在目录执行以下命令,更新portainer

docker stack deploy --compose-file=portainer-agent-stack.yml portainer

5.访问
首次访问有警告提示,点击高级,继续访问

6.进入portainer
在这里插入图片描述

未分类

/var/lib/docker/image 镜像的配置文件
/var/lib/docker/containers 容器的配置文件
/var/lib/docker/overlay2 镜像的原文件 和 容器实例化的地址

/var/lib/docker/containers日志清理方法

方式一 脚本实现

#!/bin/sh
# drift 
echo "==================== start clean docker containers logs =========================="

logs=$(find /var/lib/docker/containers/ -name *-json.log)

for log in $logs
        do
                echo "clean logs : $log"
                cat /dev/null > $log
        done
echo "==================== end clean docker containers logs   =========================="

该方式随着时间推移,日志会一直在

[root@drift ~]# crontab -l

	#Ansible: clean_logs
	* * 2 * * /bin/sh /server/scripts/clean_logs.sh &>/dev/null

方式二 设置docker容器日志大小

通过配置容器docker-compose 的max-size来实现

logging:
      driver: "json-file"
      options:
        max-size: "2g"      # 日志文件大小
        max-file: "10"		# 日志的数量

方式三 全局设置

配置文件 /etc/docker/daemon.json 添加log-dirver和log-opts参数
max-size=500m,意味着一个容器日志大小上限是500M,
max-file=3,意味着一个容器有三个日志,分别是id+.json、id+1.json、id+2.json。
注意:设置的日志大小,只对新建的容器有效

{
  "log-driver":"json-file",
  "log-opts": {"max-size":"500m", "max-file":"3"}
}

修改完重启
systemctl daemon-reload
systemctl restart docker

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值