docker-入门到精通

docker知识总结

参考文档 https://jiajially.gitbooks.io/dockerguide/content/chapter_fastlearn/docker_run/–volumes-from.html

1、什么是docker

​ 容器技术、虚拟化技术已经成为一种被大家广泛认可的服务器资源共享方式,容器技术可以在按需构建操作系统实例的过程当中为系统管理员提供极大的灵活性。由于hypervisor虚拟化技术仍然存在一些性能和资源使用效率方面的问题,因此容器技术(Container)结合虚拟化技术的解决方案正在我们的业务使用中高频使用。

docker-入门到精通_第1张图片

虚拟机 :是通过管理系统Hypervisor模拟出CPU、内存、网络等硬件,然后在硬件的基础上创建内核和操作系统。

优点:

  • 提供更多的资源,拥有一套完整的操作系统
  • 物理层面上的完全隔离,具有更好的安全性

缺点

  • 资源占用十分大,虚拟机实例过大,资源首先,无法启动过多

  • 虚拟机的创建流程复杂

  • 虚拟机的启动时间过长

容器:是通过Linux内核的Namespace技术实现了文件系统、进程、设备以及网络的隔离,然后通过Cgourps对CPU、内存等资源进行限制,实现容器之间的隔离

Namespace是linux内核用来隔离内核资源的方式,是对全局系统资源的一种封装隔离,是的处于不同namespace 的进程拥有独立的全局系统资源,改变一个namespace中的系统资源只会影响当前namespace里的进程,对其他namespace的进程没有影响

优点:

  • **更高效的虚拟化:**系统资源的利用率更高。无论是应用执行速度、内存损耗或者文件存储速度,都要比传统虚拟机技术更高效。可以运行更多的应用
  • **更快的启动时间:**传统的虚拟机技术启动应用服务往往需要数分钟,而 Docker 容器应用,由于直接运行于宿主内核,无需启动完整的操作系统,因此可以做到秒级、甚至毫秒级的启动时间。大大的节约了开发、测试、部署的时间。
  • **更好的持续交付和部署:**可以通过dockerfile定制应用镜像来实现持续集成、持续交付、部署,往往配置一次便可重复使用。
  • **更轻松的迁移、维护、扩张:**Docker 确保了执行环境的一致性,使得应用的迁移更加容易,可以很轻易的将在一个平台上运行的应用,迁移到另一个平台上。镜像的技术,使得应用重复部分的复用更为容易,也使得应用的维护更新更加简单,基于基础镜像进一步扩展镜像也变得非常简单。

2、架构与组成

img

架构: docker是CS架构,由client客户端和server服务端组成

  • client: docker build 等客户端命令与docker daemon守护进程交互
  • server: 守护进程调用docker引擎处理镜像、容器

组成:

  • 镜像(image):镜像就是一个只读的root文件通模板,可以通过这个模板创建容器服务,一个镜像可以创建多个容器

  • **容器(container):**Docker利用容器技术,独立运行的一个或一组应用。容器是用镜像创建的运行实例。

    • 容器可以被启用,开始,停止,删除。每个容器都是相互隔离的,保证安全的平台。
    • 容器可以看作是一个简易版的Linux系统(包括root用户权限,进程空间,用户空间和网络空间等)和运行在其中的应用程序。
    • 容器的定义和镜像几乎一摸一样,也是一堆层的统一视角,唯一区别在于容器的最上面那一层是可读可写的
  • **仓库(repository):**仓库是集中存放镜像文件的场所。仓库和仓库注册服务器(Registry)是有区别的,仓库注册服务器上往往存放着多个仓库,每个仓库中又包含了多个镜像,每个镜像有不同的标签

    • 仓库分为**公开仓库(public)私有仓库(private)**两种形式

    • 最大的开放仓库是国外的 Docker Hub,存放了数量庞大的镜像供用户下载。

    • 国内的公开仓库包括阿里云,网易云都有容器服务器(需要配置镜像加速)等

3、安装与配置

docker适合centos 7 或者 8 的版本,通过以下命令查看系统配置:

uname -r
cat /etc/os-release 

docker-入门到精通_第2张图片

安装

安装gcc相关依赖
yum -y install gcc
yum -y install gcc-c++

卸载旧版本
yum remove docker \
    docker-client \
    docker-client-latest \
    docker-common \
    docker-latest \
    docker-latest-logrotate \
    docker-logrotate \
    docker-selinux \
    docker-engine-selinux \
    docker-engine
    
安装需要的软件包
yum install -y yum-utils device-mapper-persistent-data lvm2

设置stable镜像仓库
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

更新yum软件索引
centos7:  sudo yum makecache fast  
centos8执行: dnf makecache

安装docker
yum -y install docker-ce

期间遇到问题参考博客:https://blog.csdn.net/test1280/article/details/119523583
sudo yum erase podman buildah

启动docker
systemctl start docker 
开机自启
systemctl enable docker

测试
docker version #查看版本
docker run hello-world #运行hello-world镜像
docker ps #查看运行容器

配置阿里云镜像加速,如果不配的话镜像下载会从国外下载,会很慢。
mkdir -p /etc/docker #新建一个目录
vim /etc/docker/daemon.json # 新建编辑json文件

打开文件后输入
{
  "registry-mirrors": ["https://5hrp3vzq.mirror.aliyuncs.com"]
}
然后退出保存,继续执行

systemctl daemon-reload
systemctl restart docker

配置完成

卸载

# 1、卸载Docker依赖: Docker Engine,CLI和Containerd软件包
sudo yum remove docker-ce docker-ce-cli containerd.io

# 2、删除Docker资源: 所有镜像,容器和卷(主机上的镜像,容器,卷或自定义配置文件不会自动删除)
sudo rm -rf /var/lib/docker

3、交互原理

Docker是怎么工作的?

  • Docker 是一个 Client-Server 结构的系统,Docket 的守护进程运行在主机上,通过Socket从客户端访问
  • DockerServer 接收到 DockerClient 的指令,就会执行这个命令

image-20210124152058394

Docker为什么比VM快?

Docker有着比虚拟机更少的抽象层,由于Docker不需要Hypervisor实现硬件资源虚拟化,运行在Docker容器上的程序直接使用的都是实际物理机的硬件资源,因此在Cpu、内存利用率上Docker将会在效率上有明显优势。

Docker利用的是宿主机的内核,而不需要Guest OS,因此,当新建一个容器时,Docker不需要和虚拟机一样重新加载一个操作系统,避免了引导、加载操作系统内核这个比较费时费资源的过程,当新建一个虚拟机时,虚拟机软件需要加载Guest OS,这个新建过程是分钟级别的,而Docker由于直接利用宿主机的操作系统则省略了这个过程,因此新建一个Docker容器只需要几秒钟。

Docker容器 虚拟机(VM)
操作系统 与宿主机共享OS 宿主机OS上运行虚拟机OS
存储大小 镜像小,便于存储与传输 镜像庞大(vmdk等)
运行性能 几乎无额外性能损失 操作系统额外的cpu、内存消耗
移植性 轻便、灵活、适用于Linux 笨重、与虚拟化技术耦合度高
硬件亲和性 面向软件开发者 面向硬件运维者

4、常用指令

img

  • 帮助指令

    # 显示docker的版本信息
    docker version
    
    # 显示docker的系统信息(包括镜像和容器数量)
    docker info
    
    # 帮助命令
    docker 命令 --help
    
  • 镜像指令

    # 查看本地主机所有的镜像
    docker images
    #可选项
    --all , -a		列出所有镜像
    --quiet , -q	只显示镜像ID
    
    # 搜索镜像
    docker search 镜像名
    # 可选项
    -f, --filter filter   根据提供的条件过滤输出
    # 例如搜索STARS大于3000的
    docker search mysql -f STARS=3000
    
    
    # 下载镜像
    docker pull 镜像名[:tag]
    docker pull mysql:latest
    
    
    # 删除镜像
    docker rmi
    # 可选项
    -f, --force      #强制删除
    docker rmi -f 镜像id #删除指定镜像
    docker rmi -f 镜像id 镜像id 镜像id #删除指定多个镜像
    docker rmi -f $(docker images -aq)  #删除全部镜像
    
    # 镜像标签
    docker tag 镜像id/镜像全名  新标签
    docker tag centos:latest centos:xiao7
    
    
    
  • 容器指令

    docker pull centos # 先拉取一个镜像
    
    # 新建容器并启动
    docker run [可选参数] image
    
    # 参数说明
    --name="Name"	 容器名字,用于区分容器
    -d				后台方式运行
    -it				使用交互方式运行,进入容器查看内容
    -p				指定容器端口(小写)
    	-p ip:主机端口:容器端口
    	-p 主机端口:容器端口(最常用)
    	-P 容器端口
    -P				随机执行端口(大写)
    -e 设置容器的环境属性配置,比如设置es的内存配置:-e ES_JAVA_OPTS="-Xms64m -Xmx512m"
    
    # 重启容器
    docker restart 容器id		
    
    # 容器停止并退出
    exit
    # 容器不停止退出
    Ctrl+p+q
    
    
    # 列出所有运行的容器
    docker ps [可选参数]
    # 参数说明
    -a		列出当前正在运行以及历史运行过的容器
    -n=?	显示最近创建的容器
    -q		只显示容器编号
    
    
    # 停止容器
    docker stop 容器id		# 停止正在运行的容器
    docker kill 容器id		# 强制停止当前容器
    
    
    
    
    # 删除指定容器,不能删除正在运行的容器,强制删除用rm -f
    docker rm 容器id/容器的name
    
    # 删除所有容器
    docker rm -f $(docker ps -aq)
    docker ps -a -q|xargs docker rm
    
    # 查看容器日志
    docker logs [可选参数] 容器ID
          --details        显示提供给日志的其他详细信息
      -f, --follow         跟踪日志输出
      -n, --tail string    指定要显示的日志条数 (默认为全部)
      -t, --timestamps     显示时间戳
    
    docker run --name centos -d centos  /bin/bash -c "while true;do echo zsr;sleep 1;done"
    docker logs -t -n 10 centos 
    
    # 查看容器中的进程
    docker top 容器ID
    
    # 查看镜像元数据
    docker inspect 镜像id\容器id
    
    
    # 方式一: 进入容器后开启一个新的终端,可在里面进行操作(常用)
    docker exec -it 容器id /bin/bash
    
    # 方式二: 进入容器正在执行的终端,不会启动新的进程
    docker attach --sig-proxy=false 容器id # control+c可以退出而不停止容器
    
    
    # 容器的导入导出
    docker export 容器id > centos.tar # 导出
    docker save 容器id > centos.tar # 导出
    docker import - 新镜像名 < centos.tar # 导入
    docker load < centos.tar # 导入
    
    # 从容器内拷贝文件到主机
    docker cp 容器id:容器内路径 目的主机路径
    
    
    # 根据容器创建新镜像
    docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
    -a :提交的镜像作者;
    -c :使用Dockerfile指令来创建镜像;
    -m :提交时的说明文字;
    -p :在commit时,将容器暂停。
    docker commit -a "xiao7" -m "测试提交" centos centos:xiao7
    
    # 查看容器的状态
    docker stats 容器id
    

5、镜像原理

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

镜像加载原理

​ Docker 的镜像实际上由一层一层的文件系统组成,这种层级的文件系统就是 UnionFS

**UnionFS(联合文件系统):**一种分层、轻量级且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不通目录挂载到同一个虚拟文件系统下(unite serveral directories into a single virtual filesystem)。

Union 文件系统是 Docker 镜像的基础,镜像可以通过分层来继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。

**特性:**一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。

image-20210127195423589

  • bootfs(boot file system): 主要包含bootloaderkernelbootloader主要是引导加载kerelLinux刚启动时会加载 bootfs文件系统,在Docker镜像的最底层时bootfs。这一层与我们典型的Linux/Unix内核是一样的,包含boot加载器和内核。当boot载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs

  • **rootfs(root file system):**在bootfs之上,包含的就是典型的 Linux系统中的 /dev、/proc、/bin、/etc 等标准文件。rootfs 就是各种不同的操作系统发行版。

​ 对于一个精简的 OSrootfs 可以很小,只需要包含最基本的命令、工具和程序库就可以了,因为底层使用的是主机的Kernel,自己只需要提供rootfs就可以了。由此可见,对于不同linux发行版,bootfs是基本一致的,rootfs会有差别,因此不同的发行版可以公用bootfs

分层理解

下载示例,可以看到,是一层一层的在下载

image-20210127200105189

为什么Docker镜像要采取这种分层的结构呢?

​ **资源共享:**如果有多个镜像从相同的Base镜像构建而来,那么宿主机只需要在磁盘上保留一份base镜像,同时内存中也只需要加载一份base镜像,这样就可以为所有的容器服务,且每一层的镜像都可以被共享。

理解

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

​ 举一个简单的例子,假如基于 Ubuntu Linux 16.04 创建一个新的镜像,这就是新镜像的第一层;如果要在该镜像中添加python包,就会在基础镜像层之上创建了新的一个镜像层;如果继续添加一个安全补丁,就会创建第三个镜像层

在这里插入图片描述

下图中展示了一个稍微复杂的三层镜像,在外部看来整个镜像只有 6 个文件,这是因为最上层中的文件7 是文件 5 的一个更新版本

img

这种情况下,上层镜像层中的文件覆盖了底层镜像层中的文件。这样就使得文件的更新版本作为一个新镜像层添加到镜像当中。
Docker 通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统。

运行原理

​ Docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部!

​ 这一层就是我们通常说的容器层,容器之下的都叫镜像层!

image-20210128121203472

6、容器数据卷

数据卷:我们希望Docker容器产生的数据可以自动同步到本地,这样容器删了数据并不会丢失;同时数据也可在容器之间共享。这就是卷技术,也就是目录的挂载,将容器内的目录挂载到linux

使用指令:

# 启动容器时指定挂载的数据卷目录
docker run -it -v 主机目录:容器内目录 镜像id

# 不指定路径,匿名挂载
docker run --name centos-2 -v  centos-2:/home -d centos  /bin/bash -c "while true;do echo zsr;sleep 1;done"

# 查看挂载的数据卷
docker volume ls

# 删除数据卷
docker volume rm 容器卷id

# 查看数据卷的具体内容
docker volume inspect centos-2

# 数据卷容器之间的共享
docker run -it --name centos-1 --volumes-from 被共享的容器id centos 

# 清除无用容器卷
docker volume pure

数据卷特点: 主机和容器之间的数据会互相同步

数据卷容器特点: 容器共享另一个容器的数据卷

7、dockerfile

dockerfile是用来构建docker镜像的文件

image-20210129213822710

基础知识

  1. 每个保留关键字(指令)都必须是大写字母
  2. 执行顺序从上往下顺序执行
  3. #代表注释
  4. 每条指令都会创建并提交一个新的镜像层

image-20210129213927281

常用指令

可参考文档:https://www.runoob.com/docker/docker-dockerfile.html

img

每种指令的用法

# 1、FROM
FROM java:8 # 挂载java基础镜像环境

# 2、MAINTAINER
MAINTAINER xioa7<[email protected]> # 设置姓名邮箱

# 3、RUN 编译镜像时执行的脚本 是在 docker build的时候执行
# RUN <命令行命令>
RUN yum -y install wget
RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"
RUN tar -xvf redis.tar.gz # 创建三层镜像

RUN yum -y install wget \
    && wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \
    && tar -xvf redis.tar.gz # 只创建一层镜像
    
# RUN ["可执行文件", "参数1", "参数2"]
RUN ["./test.php", "dev", "offline"] # 等价于 RUN ./test.php dev offline


# 4、CMD设置容器的启动命令,在docker run 时运行。如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效。
CMD  
CMD ["<可执行文件或命令>","","",...] 
CMD ["","",...]  # 该写法是为 ENTRYPOINT 指令指定的程序提供默认参数


# 5、LABEL 设置镜像标签
LABEL = = = ...
LABEL org.opencontainers.image.authors="runoob"

# 6、EXPOSE 设置镜像暴露的端口
EXPOSE <端口1> [<端口2>...] # 仅仅只是声明端口。帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射。

# 7、ENV 设置环境变量,定义了环境变量,那么在后续的指令中,就可以使用这个环境变量。
ENV NODE_VERSION 7.2.0

RUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz" \
  && curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc"


# 8、ADD、COPY 构建镜像时复制内容到镜像中
COPY [--chown=:] <源路径1>...  <目标路径>
COPY hom* /mydir/
COPY hom?.txt /mydir/


# 9、ENTRYPOINT 设置程序入口
ENTRYPOINT ["","","",...]
优点:在执行 docker run 的时候可以指定 ENTRYPOINT 运行所需的参数。
注意:如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。
例子:
FROM nginx

ENTRYPOINT ["nginx", "-c"] # 定参
CMD ["/etc/nginx/nginx.conf"] # 变参是给上面的提供默认参数

# 9、VOLUME 设置容器的挂载卷
VOLUME ["<路径1>", "<路径2>"...]
VOLUME <路径>

# 10、USER 设置执行后续命令的用户
USER <用户名>[:<用户组>]

# 11、WORKDIR 设置工作目录
WORKDIR <工作目录路径>

# 12、ARG 构建参数,与 ENV 作用一致。不过作用域不一样。ARG 设置的环境变量仅对 Dockerfile 内有效,也就是说只有 docker build 的过程中有效,构建好的镜像内不存在此环境变量。
ARG <参数名>[=<默认值>]

# 13、ONBUILD 用于延迟构建命令的执行。简单的说,就是 Dockerfile 里用 ONBUILD 指定的命令,在本次构建镜像的过程中不会执行(假设镜像为 test-build)。当有新的 Dockerfile 使用了之前构建的镜像 FROM test-build ,这时执行新镜像的 Dockerfile 构建时候,会执行 test-build 的 Dockerfile 里的 ONBUILD 指定的命令。

ONBUILD <其它指令>

# 14、STOPSINGLE 指令设置将发送到容器以退出的系统调用信号。这个信号可以是一个有效的无符号数字,与内核的syscall表中的位置相匹配,例如9,或者是SIGNAME格式的信号名,例如SIGKILL。
STOPSINGLE 15

构建

例子

FROM centos
MAINTAINER zsr<[email protected]>

ENV MYPATH /usr/local
WORKDIR $MYPATH

RUN yum -y install vim
RUN yum -y install net-tools

EXPOSE 8088

CMD echo $MYPATH
CMD echo "----end----"
CMD /bin/bash

构建镜像

docker build -f 文件名 -t 镜像名:[tag] .

8、可视化portainer

拉取运行

docker run -d -p 8088:9000 \
--restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer

打开服务远程连接

docker-入门到精通_第3张图片

连接不上需要开放2375端口

1. 编辑docker.service
vim /usr/lib/systemd/system/docker.service
找到 ExecStart字段修改如下
#ExecStart=/usr/bin/dockerd-current -H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock 
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock

2. 重启docker重新读取配置文件,重新启动docker服务
systemctl daemon-reload
systemctl restart docker

3. 开放防火墙端口
firewall-cmd --zone=public --add-port=6379/tcp --permanent

4.刷新防火墙
firewall-cmd --reload

9、镜像仓库

9.1、Docker Hub仓库

  • **登录仓库 **

    docker login -u 账号名
    
  • 打上标签

    docker tag centos:xiao7 15625764185/centos:xiao7
    docker tag 原镜像	账户名/镜像名:版本号 # 格式
    
  • 推送到仓库

     docker push 15625764185/centos:xiao7
    

docker-入门到精通_第4张图片

9.2、阿里云仓库

image-20210216115915960
image-20210216120928206

image-20210216121405524

image-20210216184331575

9.3、Harbor企业级仓库

安装docker-compose,建议手动下载上传

# 下载github的文件,连接不上的话配置hosts 进入/etc/hosts,先去https://www.ipaddress.com查询指定域名的ip
140.82.112.3 github.com
185.199.108.133 raw.githubusercontent.com
185.199.109.133 raw.githubusercontent.com
185.199.110.133 raw.githubusercontent.com
185.199.111.133 raw.githubusercontent.com
151.101.1.194 github.global.ssl.fastly.net

# 这个命令下载了个错的
sudo curl -L "https://github.com/docker/compose/releases/download/v2.16.0/docker-compose--$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
# 指定具体的文件
sudo curl -L "https://github.com/docker/compose/releases/download/v2.16.0/docker-compose-linux-aarch64" -o /usr/local/bin/docker-compose

sudo curl -L "https://github.com/docker/compose/releases/download/v2.16.0/docker-compose-linux-x86_64" -o /usr/local/bin/docker-compose
 
sudo chmod +x /usr/local/bin/docker-compose

docker-compose --version

安装harbor

**https相关配置参考:**https://glory.blog.csdn.net/article/details/127817508?spm=1001.2101.3001.6650.2&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EOPENSEARCH%7ERate-2-127817508-blog-87954438.pc_relevant_3mothn_strategy_and_data_recovery&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EOPENSEARCH%7ERate-2-127817508-blog-87954438.pc_relevant_3mothn_strategy_and_data_recovery&utm_relevant_index=3

# 下载压缩包
wget https://github.com/goharbor/harbor/releases/download/v2.5.3/harbor-offline-installer-v2.5.3.tgz

# 解压
tar -vxf harbor-offline-installer-v2.6.3.tar

#修改配置文件
cd harbor
cp harbor.yml.tmpl harbor.yml
vi harbor.yml
hostname:改成自己的域名或者ip
https相关注释掉,局域网不需要
harbor_admin_password:设置管理后台密码

# 安装
./install.sh


# 登录仓库地址
docker login 仓库ip+端口

# 推送  docker push <仓库ip:端口>/<项目名称>/<镜像名>:

docker push 192.168.101.20/baozi/dotnet6demo:v1

10、网络原理

基本原理

当我们用ip addr命令查看服务器内部网络地址时,可以发现三个地址:

  • 127.0.0.1 本机回环地址
  • 10.211.55.3 服务器内网IP地址
  • 172.17.0.1 docker0地址

这里的docker0地址就是安装docker时,采用 桥接模式 使用 evth-pair 技术分配的地址

  • 给该容器分配一个ip

docker-入门到精通_第5张图片

每次新增的网络地址都是一对一对的70/71,这就是evth-pair技术,就是一对虚拟设备接口,成对出现,一段连着协议,一段彼此相连;容器内的70连接了主机的71;

evth-pair充当了一个桥梁,实现了主机可以ping通容器内部ip地址,用于连接各种虚拟网络设备

查看网络

可用docker netowork命令查看该网桥中的所有配置

[root@localhost ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
d5c5483d1a8e   bridge    bridge    local
34d522c7863f   host      host      local
dcd894499677   none      null      local
[root@localhost ~]# docker network inspect bridge 
[
    {
        "Name": "bridge",
        "Id": "d5c5483d1a8ed4d862cd515f582324d469ef645ffc577b5d3deb84a516c64ac2",
        "Created": "2023-02-10T18:35:24.437139277-05:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "29939ea09b2d6926d4dd2fb6ef19f75180fb1381d64030fa88f52feba04faf08": {
                "Name": "centos",
                "EndpointID": "3dccf14953bdcc76899cd2493ac22411576d2fd6f36fa321eca419c947d9803b",
                "MacAddress": "02:42:ac:11:00:03",
                "IPv4Address": "172.17.0.3/16",
                "IPv6Address": ""
            }
        },
        "Options": {
            "com.docker.network.bridge.default_bridge": "true",
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}
    }
]

**结论:**容器和容器之间是可以互相ping通的

image-20210216214529859

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

image-20210216221256027

Docker 使用的是Linux的桥接,宿主机中是一个Docker容器的网桥docker0
Docker 中所有的网络接口都是虚拟的,转发效率高,只要容器删除,对应的网桥就删除

容器互联–link

如果我们编写了一个微服务,连接数据库的ip地址变化了,此时数据连接就会断开,服务不可用;如果此时能够通过容器名字连接数据库,就可以解决数据库连接的问题;

#如果tomcat01直接通过pingtomcat02的容器名,会报错

[root@zsr ~]# docker exec -it tomcat01 ping tomcat02
ping: tomcat02: Name or service not known
那么如何解决这个问题呢?可以在创建容器时用--link指定连接的容器,此时就可以通过容器名来ping通了
[root@zsr ~]# docker run -d -P --name tomcat03 --link tomcat01 tomcat
1cc06da893c10d4ef1bdf7e590860b44cf55a0c506b57b64dda44551ef06d816
[root@zsr ~]# docker exec -it tomcat03 ping tomcat01
PING tomcat01 (172.18.0.2) 56(84) bytes of data.
64 bytes from tomcat01 (172.18.0.2): icmp_seq=1 ttl=64 time=0.127 ms
64 bytes from tomcat01 (172.18.0.2): icmp_seq=2 ttl=64 time=0.103 ms
64 bytes from tomcat01 (172.18.0.2): icmp_seq=3 ttl=64 time=0.103 ms

但是反过来ping则无法ping通

[root@zsr ~]# docker exec -it tomcat01 ping tomcat03
ping: tomcat03: Name or service not known

**原理:**通过–link 使tomcat03 在本地hosts中配置了 tomcat02的ip与容器名的映射

image-20210301165801064

自定义网络

网络模式

  • bridge:桥接(默认)
  • none:不配置网络
  • host:主机模式,和宿主机共享网络
  • container:容器网络联通(使用少!)

建议自定义一个网络,所有的服务都在自定义的网络中进行使用!

创建一个网络mynet,采用默认的桥接模式,子网地址192.168.0.0,网关192.168.0.1

[root@zsr ~]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
2e6be259e1f43f884fbf9e24aa3cc1b238b91bd1e9be3ba0abcfbefd3e106450
[root@zsr ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
81fa37acd3b5   bridge    bridge    local
d1c3276f2d1f   host      host      local
2e6be259e1f4   mynet     bridge    local
40b12350fa4a   none      null      local

image-20210220223210904

我们指定使用自定义网络mynet来启动两个容器

[root@zsr ~]# docker run -d -P --name mynet-tomcat01 --net mynet tomcat
2795bf15cd21ec608c02840bd7488942da4838d47662b0b204e663003fa49a3b
[root@zsr ~]# docker run -d -P --name mynet-tomcat02 --net mynet tomcat
41b416dbf35eb55164ffe024d120a17db60aa0a501f20ef3ce40d3c180a67517

再次测试ping连接,发现自定义的网络解决了docker0的缺点,可以直接通过容器名来访问

应用场景:

不同的集群(redismysql)用不同的网络,使用自己的子网,保证集群的安全及健康

11、docker-compose

参考文档:https://yeasy.gitbook.io/docker_practice/compose/compose_file、https://www.runoob.com/docker/docker-compose.html

Compose 是用于定义和运行多容器 Docker 应用程序的工具。通过 Compose,您可以使用 YML 文件来配置应用程序需要的所有服务。然后,使用一个命令,就可以从 YML 文件配置中创建并启动所有服务。

安装

# 下载github的文件,连接不上的话配置hosts 进入/etc/hosts,先去https://www.ipaddress.com查询指定域名的ip
140.82.112.3 github.com
185.199.108.133 raw.githubusercontent.com
185.199.109.133 raw.githubusercontent.com
185.199.110.133 raw.githubusercontent.com
185.199.111.133 raw.githubusercontent.com
151.101.1.194 github.global.ssl.fastly.net

# 这个命令下载了个错的
sudo curl -L "https://github.com/docker/compose/releases/download/v2.16.0/docker-compose--$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
# 指定具体的文件
sudo curl -L "https://github.com/docker/compose/releases/download/v2.16.0/docker-compose-linux-aarch64" -o /usr/local/bin/docker-compose

sudo curl -L "https://github.com/docker/compose/releases/download/v2.16.0/docker-compose-linux-x86_64" -o /usr/local/bin/docker-compose
 
sudo chmod +x /usr/local/bin/docker-compose

docker-compose --version

配置示例

# 配置示例
version: '3'
services:
  web:
    build: .
    ports:
   - "5000:5000"
    volumes:
   - .:/code
    - logvolume01:/var/log

启动命令

docker-compose up 

指令详解

version

指定本 yml 依从的 compose 哪个版本制定的。

build

指定为构建镜像上下文路径:

例如 webapp 服务,指定为从上下文路径 ./dir/Dockerfile 所构建的镜像:

version: "3.7"
services:
  webapp:
    build: ./dir

或者,作为具有在上下文指定的路径的对象,以及可选的 Dockerfile 和 args:

version: "3.7"
services:
  webapp:
    build:
      context: ./dir
      dockerfile: Dockerfile-alternate
      args:
        buildno: 1
      labels:
        - "com.example.description=Accounting webapp"
        - "com.example.department=Finance"
        - "com.example.label-with-empty-value"
      target: prod
  • context:上下文路径。
  • dockerfile:指定构建镜像的 Dockerfile 文件名。
  • args:添加构建参数,这是只能在构建过程中访问的环境变量。
  • labels:设置构建镜像的标签。
  • target:多层构建,可以指定构建哪一层。

cap_add,cap_drop

添加或删除容器拥有的宿主机的内核功能。

cap_add:
  - ALL # 开启全部权限

cap_drop:
  - SYS_PTRACE # 关闭 ptrace权限

cgroup_parent

为容器指定父 cgroup 组,意味着将继承该组的资源限制。

cgroup_parent: m-executor-abcd

command

覆盖容器启动的默认命令。

command: ["bundle", "exec", "thin", "-p", "3000"]

container_name

指定自定义容器名称,而不是生成的默认名称。

container_name: my-web-container

depends_on

设置依赖关系。

  • docker-compose up :以依赖性顺序启动服务。在以下示例中,先启动 db 和 redis ,才会启动 web。
  • docker-compose up SERVICE :自动包含 SERVICE 的依赖项。在以下示例中,docker-compose up web 还将创建并启动 db 和 redis。
  • docker-compose stop :按依赖关系顺序停止服务。在以下示例中,web 在 db 和 redis 之前停止。
version: "3.7"
services:
  web:
    build: .
    depends_on:
      - db
      - redis
  redis:
    image: redis
  db:
    image: postgres

**注意:**web 服务不会等待 redis db 完全启动 之后才启动。

deploy

指定与服务的部署和运行有关的配置。只在 swarm 模式下才会有用。

version: "3.7"
services:
  redis:
    image: redis:alpine
    deploy:
      mode:replicated
      replicas: 6
      endpoint_mode: dnsrr
      labels: 
        description: "This redis service label"
      resources:
        limits:
          cpus: '0.50'
          memory: 50M
        reservations:
          cpus: '0.25'
          memory: 20M
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3
        window: 120s

可以选参数:

endpoint_mode:访问集群服务的方式。

endpoint_mode: vip 
# Docker 集群服务一个对外的虚拟 ip。所有的请求都会通过这个虚拟 ip 到达集群服务内部的机器。
endpoint_mode: dnsrr
# DNS 轮询(DNSRR)。所有的请求会自动轮询获取到集群 ip 列表中的一个 ip 地址。

labels:在服务上设置标签。可以用容器上的 labels(跟 deploy 同级的配置) 覆盖 deploy 下的 labels。

mode:指定服务提供的模式。

  • replicated:复制服务,复制指定服务到集群的机器上。

  • global:全局服务,服务将部署至集群的每个节点。

  • 图解:下图中黄色的方块是 replicated 模式的运行情况,灰色方块是 global 模式的运行情况。

    docker-入门到精通_第6张图片

replicas:mode 为 replicated 时,需要使用此参数配置具体运行的节点数量。

resources:配置服务器资源使用的限制,例如上例子,配置 redis 集群运行需要的 cpu 的百分比 和 内存的占用。避免占用资源过高出现异常。

restart_policy:配置如何在退出容器时重新启动容器。

  • condition:可选 none,on-failure 或者 any(默认值:any)。
  • delay:设置多久之后重启(默认值:0)。
  • max_attempts:尝试重新启动容器的次数,超出次数,则不再尝试(默认值:一直重试)。
  • window:设置容器重启超时时间(默认值:0)。

rollback_config:配置在更新失败的情况下应如何回滚服务。

  • parallelism:一次要回滚的容器数。如果设置为0,则所有容器将同时回滚。
  • delay:每个容器组回滚之间等待的时间(默认为0s)。
  • failure_action:如果回滚失败,该怎么办。其中一个 continue 或者 pause(默认pause)。
  • monitor:每个容器更新后,持续观察是否失败了的时间 (ns|us|ms|s|m|h)(默认为0s)。
  • max_failure_ratio:在回滚期间可以容忍的故障率(默认为0)。
  • order:回滚期间的操作顺序。其中一个 stop-first(串行回滚),或者 start-first(并行回滚)(默认 stop-first )。

update_config:配置应如何更新服务,对于配置滚动更新很有用。

  • parallelism:一次更新的容器数。
  • delay:在更新一组容器之间等待的时间。
  • failure_action:如果更新失败,该怎么办。其中一个 continue,rollback 或者pause (默认:pause)。
  • monitor:每个容器更新后,持续观察是否失败了的时间 (ns|us|ms|s|m|h)(默认为0s)。
  • max_failure_ratio:在更新过程中可以容忍的故障率。
  • order:回滚期间的操作顺序。其中一个 stop-first(串行回滚),或者 start-first(并行回滚)(默认stop-first)。

:仅支持 V3.4 及更高版本。

devices

指定设备映射列表。

devices:
  - "/dev/ttyUSB0:/dev/ttyUSB0"

dns

自定义 DNS 服务器,可以是单个值或列表的多个值。

dns: 8.8.8.8

dns:
  - 8.8.8.8
  - 9.9.9.9

dns_search

自定义 DNS 搜索域。可以是单个值或列表。

dns_search: example.com

dns_search:
  - dc1.example.com
  - dc2.example.com

entrypoint

覆盖容器默认的 entrypoint。

entrypoint: /code/entrypoint.sh

也可以是以下格式:

entrypoint:
    - php
    - -d
    - zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20100525/xdebug.so
    - -d
    - memory_limit=-1
    - vendor/bin/phpunit

env_file

从文件添加环境变量。可以是单个值或列表的多个值。

env_file: .env

也可以是列表格式:

env_file:
  - ./common.env
  - ./apps/web.env
  - /opt/secrets.env

environment

添加环境变量。您可以使用数组或字典、任何布尔值,布尔值需要用引号引起来,以确保 YML 解析器不会将其转换为 True 或 False。

environment:
  RACK_ENV: development
  SHOW: 'true'

expose

暴露端口,但不映射到宿主机,只被连接的服务访问。

仅可以指定内部端口为参数:

expose:
 - "3000"
 - "8000"

extra_hosts

添加主机名映射。类似 docker client --add-host。

extra_hosts:
 - "somehost:162.242.195.82"
 - "otherhost:50.31.209.229"

以上会在此服务的内部容器中 /etc/hosts 创建一个具有 ip 地址和主机名的映射关系:

162.242.195.82  somehost
50.31.209.229   otherhost

healthcheck

用于检测 docker 服务是否健康运行。

healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost"] # 设置检测程序
  interval: 1m30s # 设置检测间隔
  timeout: 10s # 设置检测超时时间
  retries: 3 # 设置重试次数
  start_period: 40s # 启动后,多少秒开始启动检测程序

image

指定容器运行的镜像。以下格式都可以:

image: redis
image: ubuntu:14.04
image: tutum/influxdb
image: example-registry.com:4000/postgresql
image: a4bc65fd # 镜像id

logging

服务的日志记录配置。

driver:指定服务容器的日志记录驱动程序,默认值为json-file。有以下三个选项

driver: "json-file"
driver: "syslog"
driver: "none"

仅在 json-file 驱动程序下,可以使用以下参数,限制日志得数量和大小。

logging:
  driver: json-file
  options:
    max-size: "200k" # 单个文件大小为200k
    max-file: "10" # 最多10个文件

当达到文件限制上限,会自动删除旧得文件。

syslog 驱动程序下,可以使用 syslog-address 指定日志接收地址。

logging:
  driver: syslog
  options:
    syslog-address: "tcp://192.168.0.42:123"

network_mode

设置网络模式。

network_mode: "bridge"
network_mode: "host"
network_mode: "none"
network_mode: "service:[service name]"
network_mode: "container:[container name/id]"

networks

配置容器连接的网络,引用顶级 networks 下的条目 。

services:
  some-service:
    networks:
      some-network:
        aliases:
         - alias1
      other-network:
        aliases:
         - alias2
networks:
  some-network:
    # Use a custom driver
    driver: custom-driver-1
  other-network:
    # Use a custom driver which takes special options
    driver: custom-driver-2

aliases :同一网络上的其他容器可以使用服务名称或此别名来连接到对应容器的服务。

restart

  • no:是默认的重启策略,在任何情况下都不会重启容器。
  • always:容器总是重新启动。
  • on-failure:在容器非正常退出时(退出状态非0),才会重启容器。
  • unless-stopped:在容器退出时总是重启容器,但是不考虑在Docker守护进程启动时就已经停止了的容器
restart: "no"
restart: always
restart: on-failure
restart: unless-stopped

注:swarm 集群模式,请改用 restart_policy。

secrets

存储敏感数据,例如密码:

version: "3.1"
services:

mysql:
  image: mysql
  environment:
    MYSQL_ROOT_PASSWORD_FILE: /run/secrets/my_secret
  secrets:
    - my_secret

secrets:
  my_secret:
    file: ./my_secret.txt

security_opt

修改容器默认的 schema 标签。

security-opt:
  - label:user:USER   # 设置容器的用户标签
  - label:role:ROLE   # 设置容器的角色标签
  - label:type:TYPE   # 设置容器的安全策略标签
  - label:level:LEVEL  # 设置容器的安全等级标签

stop_grace_period

指定在容器无法处理 SIGTERM (或者任何 stop_signal 的信号),等待多久后发送 SIGKILL 信号关闭容器。

stop_grace_period: 1s # 等待 1 秒
stop_grace_period: 1m30s # 等待 1 分 30 秒 

默认的等待时间是 10 秒。

stop_signal

设置停止容器的替代信号。默认情况下使用 SIGTERM 。

以下示例,使用 SIGUSR1 替代信号 SIGTERM 来停止容器。

stop_signal: SIGUSR1

sysctls

设置容器中的内核参数,可以使用数组或字典格式。

sysctls:
  net.core.somaxconn: 1024
  net.ipv4.tcp_syncookies: 0

sysctls:
  - net.core.somaxconn=1024
  - net.ipv4.tcp_syncookies=0

tmpfs

在容器内安装一个临时文件系统。可以是单个值或列表的多个值。

tmpfs: /run

tmpfs:
  - /run
  - /tmp

ulimits

覆盖容器默认的 ulimit。

ulimits:
  nproc: 65535
  nofile:
    soft: 20000
    hard: 40000

volumes

将主机的数据卷或着文件挂载到容器里。

version: "3.7"
services:
  db:
    image: postgres:latest
    volumes:
      - "/localhost/postgres.sock:/var/run/postgres/postgres.sock"
      - "/localhost/data:/var/lib/postgresql/data"

12、SpringBoot、Idea整合使用docker

创建SpringBoot项目,maven的配置,其余参考:https://blog.csdn.net/weixin_38650898/article/details/105158143

 <build>
        <finalName>${project.artifactId}finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-maven-pluginartifactId>
                <version>${springboot-maven.version}version>
            plugin>
            <plugin>
                <groupId>com.spotifygroupId>
                <artifactId>docker-maven-pluginartifactId>
                <version>${docker-maven-plugin.version}version>
                <configuration>
                    <imageName>117.50.173.172/${project.build.finalName}:${project.version}imageName>
                    <dockerDirectory>${project.basedir}/src/main/dockerdockerDirectory>
                    <dockerHost>117.50.173.172dockerHost>
                    <resources>
                        <resource>
                            <targetPath>/targetPath>
                            <directory>${project.build.directory}directory>
                            <include>${project.build.finalName}.jarinclude>
                        resource>
                    resources>
                    
                    <buildArgs>
                        <JAR_FILE>${project.build.finalName}.jarJAR_FILE>
                    buildArgs>
                    <pushImage>truepushImage>
                configuration>
            plugin>
        plugins>
    build>

你可能感兴趣的:(运维部署,docker,容器,运维)