• 深入理解Docker


    1 Docker理论

    1.1 背景知识

    ​ **传统软件开发与运维痛点:**一款产品从开发到上线,从操作系统到运行环境,再到应用配置。作为开发+运维之间的协作我们需要关心很多东西,这也是很多互联网公司都不得不面对的问题,特别是各种版本的迭代之后,不同版本环境的兼容,对运维人员都是考验。Docker之所以发展如此迅速,也是因为它对此给出了一个标准化的解决方案。环境配置如此麻烦,换一台机器,就要重来一次,费力费时。很多人想到,能不能从根本上解决问题,软件可以带环境安装? 也就是说,安装的时候,把原始环境一模一样地复制过来,消除协作编码时“在我的机器上可正常工作,在他人机器上不能运行”的问题。
    从而打破之前开发人员只提供代码(代码即应用)的方式,改为提交Docker镜像包括(运行文档、配置环境、运行环境、运行依赖包、操作系统发行环境),即镜像即应用。

    1.2 是什么

    ​ Docker是基于Go语言实现的云开源项目。Docker的主要目标是"Build,Ship and Run Any App,Anywhere",也就是通过对应用组件的封装、分发、部署、运行等生命周期的管理,使用户的APP (可以是一个WEB应用或数据库应用等)及其运行环境能够做到“一次封装,到处运行”。

    ​ Linux容器技术的出现就解决了这样一个问题,而Docker就是在它的基础上发展过来的。将应用运行在Docker容器上面,而Docker容器在任何操作系统上都是一致的,这就实现了跨平台、跨服务器。只需要一次配置好环境,换到别的机子上就可以一键部署,大大简化了操作。

    在这里插入图片描述

    与虚拟机的区别?
    虚拟机(virtual machine)就是带环境安装的一种解决方案。它可以在一种操作系统里面运行另一种操作系统,比如在Windows系统里面运行Linux系统。应用程序对此毫无感知,因为虚拟机看上去跟真实系统一模一样,而对于底层系统来说,虚拟机就是一个普通文件,不需要了就删掉,对其他部分毫无影响。这类虚拟机完美的运行了另一套系统,能够使应用程序,操作系统和硬件三者之间的逻辑不变。

    虚拟机的缺点:
    1、资源占用多 2、冗余步骤多 3、启动慢(分钟级别)

    在这里插入图片描述

    1.3 Docker基本三要素

    仓库Repository + 镜像Image + 容器Container

    在这里插入图片描述

    仓库Repository—>镜像Image(类Person)–>容器Container(对象p1、p2)

    1. 仓库Repository是存放镜像文件的场所,仓库Repository与仓库注册器Registry是有区别的,仓库注册服务器上往往存放多个仓库,每个仓库有多个镜像,每个镜像有不同的标签tag(仓库分为公开仓库public和私有库private,最大的仓库Docker Hub,但由于其服务器在国外,从中拉去镜像速度很慢,国内一般使用的是阿里云、网易云。)
    2. 镜像Image就是从docker Hub仓库拉取到本地的一个只读的模版,镜像Image用来创建容器Container,一个镜像可以创建多个容器
      镜像Image(类)—>容器Container(对象)
    3. Docker本身是一个容器运行载体或称之为管理引擎。我们把应用程序和配置依赖打包好形成一个可交付的运行环境,这个打包好的运行环境就似乎image镜像文件。只有通过这个镜像文件才能生成Docker容器(集装箱)。

    1.4 镜像原理

    在这里插入图片描述

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

    ​ UnionFS (联合文件系统) : Union文件系统(UnionFS) 是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union 文件系统是Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。

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

    1.5 安装教程

    1. Docker官网:https://www.docker.com
    2. Docker Hub官网:https://hub.docker.com
    3. MAC安装教程:https://docs.docker.com/desktop/install/mac-install/
    4. LinuxC安装教程
    
    • 1
    • 2
    • 3
    • 4
    # 1.移除以前docker相关包
    	yum remove docker* 															
    # 2.配置yum源
        sudo yum install -y yum-utils
        sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo 
    
    # 3.安装docker并启动
        sudo yum install -y docker-ce docker-ce-cli containerd.io  					# 安装docker及其组件
        yum install -y docker-ce-20.10.7 docker-ce-cli-20.10.7  containerd.io-1.4.6 # 以下是在安装k8s的时候使用,暂时不安装
        systemctl enable docker --now		# 启动docker,并设置开机自启动,首次优先使用该命令
        service docker status				# 查看状态
        service docker start        		# 启动
        service docker stop					# 停止
    
    # 4.配置加速
        sudo mkdir -p /etc/docker
        sudo tee /etc/docker/daemon.json <<-'EOF'
        {
          "registry-mirrors": ["https://82m9ar63.mirror.aliyuncs.com"],
          "exec-opts": ["native.cgroupdriver=systemd"],
          "log-driver": "json-file",
          "log-opts": {
            "max-size": "100m"
          },
          "storage-driver": "overlay2"
        }
        EOF
    
        sudo systemctl daemon-reload
        sudo systemctl restart docker
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    2 Docker常用命令

    2.0 防火墙相关命令

    sudo firewall-cmd --list-all --zone=public                         # 查看防火墙对外提供访问的接口
    sudo firewall-cmd --zone=public --add-port=80/tcp --permanent      # 开放TCP端口80(HTTP)
    sudo firewall-cmd --zone=public --remove-port=80/tcp --permanent   # 关闭TCP端口80(HTTP
    sudo firewall-cmd --permanent --query-port=80/tcp                  # 查看端口是否开启
    service firewalld status
    service firewalld stop
    service firewalld start
    service firewalld restart
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    2.1 镜像命令

    1 帮助命令:
    	docker version
    	docker info
    	docker --help
    
    2 镜像命令:
    	1、列出本地镜像:docker images [-options]
    		-a:列出本地所有镜像
    		-q:只显示镜像ID
    		--digests:显示镜像的摘要信息
    		--no-trunc:显示完整的镜像信息
    		docker images -a
    		docker images -q
    	2、查询DockerHub镜像:docker search [-options] 镜像名
    		docker search tomcat:列出tomcat的镜像
    		docker search --no-trunc tomcat:显示完整的镜像描述
    	3、下载镜像到本机:docker pull 镜像名
            docker pull tomcat   		下载最新镜像tomcat,等同于docker pull tomcat:latest
            docker pull redis:6.2.4 	下载指定版本镜像
    	4、删除本机镜像:docker rmi -f 镜像名/镜像id
    		docker rmi [-f] tomcat
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    在这里插入图片描述

    2.2 容器命令

    容器命令:有镜像才能实例化容器(提前下载一个centos镜像仅有200MB)
    	1、新建并启动一个容器:docker run [-options] 具体镜像名称:版本号 /bin/bash:
    		--name:容器的新别名
    		-i:以交互方式启动容器,通常与-t同时使用
    		-t:为容器分配一个伪输入终端
    		-d:以守护进程方式启动容器
    
    以交互方式启动容器(为主):前台启动
    		docker run –it --name my-centos centos:7 /bin/bash
    以守护进程方式启动容器:运行在后台
    		docker run -d --name=mynginx --restart=always -p 88:80 nginx
    
    	2、列出所有正在运行的容器: docker ps [-options] 
            -l:显示最近创建的容器
            -n 2:显示最近2个创建的容器
            -a:显示当前多元的正在运行的容器+历史上运行过的
            -q:静默模式,只显示容器编号
            --no-trunc:不截断输出显示
        
        3、退出容器
            exit:			在容器内,关闭该容器并推出
            ctrl+P+Q: 在容器内,关闭该容器但是不推出
    	
        4、停止容器				docker stop 容器名称或容器id
        5、强制停止容器		   docker kill容器名称或容器id
        6、重启容器	 			docker restart 容器名称或容器id
        7、删除容器				docker rm 容器名称或容器id
        8、查看容器日志		   docker logs [-options] 容器名称或容器id
        	docker logs -f 3063af3e3f86    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    2.3 进阶命令

    1、进容器内部
    	docker exec -it 容器id  /bin/bash  # 在新的容器中打开新的命令终端,可以启动新的进程
    2、挂载数据到外部修改
    	docker run --name=mynginx \ 
    	-d --restart=always \
    	-p  88:80 \
    	-v /data/html:/usr/share/nginx/html:ro \ # 修改页面只需要去主机的 /data/html
    	nginx:latest 
    3、镜像分享方案一
        docker save -o mynginx.tar nginx # 将镜像保存成压缩包
        docker load -i abc.tar 			 # 别的机器将压缩包加载为镜像
    4、镜像分享方案二【需要docker hub账号】
    	docker commit -m "首页变化" 341d81f7504f guignginx:v1.0  # 将自己修改好的镜像提交
    	在docker hub 注册仓库
    	docker tag guignginx:v1.0 leifengyang/guignginx:v1.0 	# 把旧镜像的名字,改成仓库要求的新版名字
    	docker login  							# 登录到docker hub
    	docker push leifengyang/guignginx:v1.0  # 推送
    	docker logout 							# 推送完成镜像后退出
    	docker pull leifengyang/guignginx:v1.0  # 别的机器下载
    5、查看容器运行情况
    	docker top 容器名称或容器id   # 查看容器内运行的进程
    	docker inspect 容器名称或容器id # 查看容器内部细节
    	docker attach 容器名称或容器id # 进入正在运行的容器并以命令行交互, 不会启动新的进程
    6、从容器内拷贝文件到主机上:		
    	docker cp 容器id: 容器路径 目的主机路径
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    在这里插入图片描述

    3. 实战之Docker部署springboot项目

    需求:

    1. 手动部署:本地IDE打包成jar,在docker环境中创建java环境容器,将jar包使用命令行拷贝至docker容器中,启动。
    2. 自动部署:通过Maven插件配置参数自动部署。(优先选这个)

    步骤一:Springboot项目配置

    1.1 添加docker的maven依赖

    		<plugins>
                <plugin>
                    <groupId>com.spotifygroupId>
                    <artifactId>docker-maven-pluginartifactId>
                    <version>1.2.2version>
                    <configuration>
                        <imageName>docker/${project.artifactId}imageName> 
                        <dockerDirectory>src/main/dockerdockerDirectory>  
                        <resources>
                            <resource>
                                <targetPath>/targetPath>
                                <directory>${project.build.directory}directory>
                                <include>${project.build.finalName}.jarinclude>
                            resource>
                        resources>
                    configuration>
                plugin>
    
                
      					
                <plugin>
                    <groupId>org.springframework.bootgroupId>
                    <artifactId>spring-boot-maven-pluginartifactId>
                    <version>2.5.2version>
                    <configuration>
                        <fork>truefork>
                    configuration>
                plugin>
            plugins>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    1.2 新建Dockfile构建镜像

    # 基于openjdk 镜像,如果镜像不是本地的会从 DockerHub 进行下载
    FROM openjdk:8
    
    # VOLUME 指向了一个/tmp的目录,由于 SpringBoot使用内置的Tomcat容器,Tomcat 默认使用/tmp作为工作目录。
    # 这个命令的效果是:在宿主机的/var/lib/docker目录下创建一个临时文件并把它链接到容器中的/tmp目录
    VOLUME /tmp
    
    # 作者
    MAINTAINER zhupeng
    
    # 将本地JAR包打包到容器中,并重命名
    ADD springboot-1.0-SNAPSHOT.jar app.jar
    
    # 声明需要暴露的端口 在Dockerfile中声明了那些端口是需要开放的,在构建容器时通过-p可以随机映射端口,如果EXPOSE没有指定端口,那么使用-p参数无效。本配置只是声明,一般我们需要在构建docker容器时使用-p(小写的p)指定开放的端口。
    EXPOSE 8080
    
    # 配置容器启动后执行的命令
    ENTRYPOINT ["java","-jar","app.jar"]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    1.3 执行构建命令

    mvn clean package -Dmaven.test.skip=true docker:build # 前提要有docker环境

    PS:如果还win执行mvn指令:mvn clean package ‘-Dmaven.test.skip=true’

    在这里插入图片描述

    步骤二 启动docker镜像

     docker images -a
     docker run -d --name my-springboot -p 8080:8080 docker/springboot-multipart [务必指定暴露端口]
     
     docker ps -a
     docker logs -f 976e5ee13513ed3
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

    步骤三:访问测试

    http://10.1.42.71:8080/test/show

    在这里插入图片描述

    坑:镜像无法启动

    如果没连接数据库的话,是可以正常启动的,但是如果application.yml连接了数据库,那就会无法启动。

    Host '10.1.42.71' is not allowed to connect to this MySQL server" MySQL不允许远程登录
    
    解决方案:
    1. update user set host = '%' where user = 'root'; 会警告报错
    2. UPDATE `mysql`.`user` SET `Host` = '%' WHERE (`Host` = 'localhost') and (`User` = 'root');
       或者手动改
    
    use mysql;
    Select user from mysql.user; MySQL 服务器中所有用户的列表
    mysql -u root -h 10.1.42.71 -p: MySQL远程登录
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    4. 实战之Dockerfile编写指南

    https://zhuanlan.zhihu.com/p/143109114

    Dockerfile中文名叫镜像描述文件,是一个包含用于组合镜像目录的文本文档,也可以叫“脚本”。他通过读取Dockerfile中的指令安装步骤自动生成镜像。

    补充:文件名称必须是:Dockerfile

    基础命令

    # 1. FROM
    # 制作基础镜像:基于openjdk 镜像
    FROM openjdk:8
    
    # 2. MAINTAINER
    # 谁创造了它(作者信息)
    MAINTAINER zhupeng
    
    # 3. WORKDIR
    # 类似于Linux中的cd命令:cd高级的地方在于,若发现没有这个目录,就自动创建出来,建议使用绝对路径
    WORKDIR /usr/local/testdir
    
    # 4.COPY
    # 文件拷贝
    # 案例一:将1.txt拷贝到根目录下。它不仅仅能拷贝单个文件,还支持Go语言风格的通配符,比如如下:
    COPY 1.txt /
    # 案例二:拷贝所有 abc 开头的文件到testdir目录下
    COPY abc* /testdir/
    # 案例三:? 是单个字符的占位符,比如匹配文件 abc1.log
    COPY abc?.log /testdir/
    
    # 5.ADD
    # 往它肚子里放点文件(会自动解压)
    ADD springboot-1.0-SNAPSHOT.jar app.jar
    # 案例一:将1.txt拷贝到根目录的abc目录下。若/abc不存在,则会自动创建
    ADD 1.txt /abc
    # 案例二:将test.tar.gz解压缩然后将解压缩的内容拷贝到/home/work/test
    ADD test.tar.gz /home/work/test
    # docker官方建议当要从远程复制文件时,尽量用curl/wget命令来代替ADD。因为用ADD的时候会创建更多的镜像层。镜像层的size也大。
    
    # ADD/COPY对比
    # 1.二者都是只复制目录中的文件,而不包含目录本身。
    # 2.COPY能干的事ADD都能干,甚至还有附加功能。
    # 3.ADD可以支持拷贝的时候顺带解压缩文件,以及添加远程文件(不在本宿主机上的文件)
    # 4.只是文件拷贝的话可以用COPY,有额外操作可以用ADD代替。
    
    
    # 6.ENV
    # 设置环境常量,方便下文引用
    ENV JAVA_HOME /usr/local/jdk1.8
    RUN ${JAVA_HOME}/bin/java -jar xxx.jar
    
    # 7.RUN
    # RUN指令是在构建镜像时运行,在构建时能修改镜像内部的文件[docker::build]
    # SHELL命令格式:RUN yum -y install vim
    # EXEC命令格式:	RUN ["yum","-y","install","vim"]
    
    # SHELL:当前shell是父进程,生成一个子shell进程去执行脚本,脚本执行完后退出子shell进程,回到当前父进程。
    # EXEC:用EXEC进程替换当前进程,并且保持PID不变,执行完毕后直接退出,不会退回原来的进程。
    # 总结:也就是说shell会创建子进程执行,EXEC不会创建子进程。推荐EXEC命令格式
    
    # 8.CMD
    # 1.容器启动时执行,而不是镜像构建时执行[docker run]
    # 2.Dockerfile中只有最后一个ENTRYPOINT会被执行,推荐用EXEC格式。
    # 3.重点在于如果容器启动的时候有其他额外的附加指令,则CMD指令不生效。
    
    # 9.ENTRYPOINT
    # 容器创建时执行,而不是镜像构建时执行。
    # Dockerfile中只有最后一个ENTRYPOINT会被执行,推荐用EXEC格式。
    ENTRYPOINT ["java","-jar","app.jar"]
    
    # 给我一个存放行李的地方(目录挂载):将本地文件夹挂载到当前容器
    VOLUME /tmp
    
    # 声明需要暴露的端口
    EXPOSE 8080
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
  • 相关阅读:
    伴随着智能汽车产业的发展,消费者购车用车过程中有哪些问题?
    深度优先与宽度优先搜索(python)
    SpringCloud服务配置介绍&Nacos实现管理配置
    20、实现短信验证码的登录注册功能
    JavaScript【回顾、面向对象、继承、正则表达式基础、字符串方法、字面量字符和元字符、转义符、字符类】(二十)
    4.1 探索LyScript漏洞挖掘插件
    写作一笔记
    基于JAVA图书馆借阅系统计算机毕业设计源码+数据库+lw文档+系统+部署
    真正的测试 =“半个产品+半个开发”?
    WPF基础的一些基本操作
  • 原文地址:https://blog.csdn.net/qq_21880261/article/details/136364960