zoukankan      html  css  js  c++  java
  • Docker学习笔记---通俗易懂

    Docker

    简介

    Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 LinuxWindows 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。

    Docker是基于 Go 语言开发的,是一个开源项目。

    文档地址:https://docs.docker.com/

    仓库地址:https://hub.docker.com/

    虚拟机技术缺点:模拟一个完整的操作系统,资源占用多,步骤冗余,启动慢。

    Docker 容器化技术:不是模拟的一个完整的操作系统。运行在宿主机的内核上。每个容器内是互相隔离的,互不影响。

    DevOps:开发 运维。

    应用更快的交付和部署。

    传统:安装各种的jar包,打包发布。

    Docker :一键打包镜像发布,测试。

    更便捷的升级和扩缩容,项目打包为一个镜像,部署应用就和搭积木一样。

    更简单的系统运维,容器化后,开发测试环境都是一致的。

    更高效的计算资源利用,Docke是内核级的虚拟化,在一个物理机上可以运行很多的容器。

    Docker安装

    Docker的基本组成

    镜像(image):

    就好比是一个模板,可通过这个镜像来创建容器服务,比如 tomcat 镜像--->run--->tomcat01容器,通过这个镜像可以创建多个容器(应用最终在容器中运行)。

    容器(container):

    Docker利用容器技术,独立运行一个或一组应用,通过镜像创建。

    启动,停止,删除,基本命令。

    仓库(repository):

    存放镜像的地方。仓库分为公有仓库和私有仓库。

    安装Docker

    环境准备:

    1. 需要会Linux基础
    2. Centos7
    3. 使用Xshell连接远程服务器操作
    4. 已经购买云服务器(以下使用阿里云)

    环境查看

    #系统内核是3.0以上的
    [root@zhourui /]# uname -r
    4.18.0-193.28.1.el8_2.x86_64
    
    #系统版本
    [root@zhourui /]# cat /etc/os-release
    NAME="CentOS Linux"
    VERSION="8 (Core)"
    ID="centos"
    ID_LIKE="rhel fedora"
    VERSION_ID="8"
    PLATFORM_ID="platform:el8"
    PRETTY_NAME="CentOS Linux 8 (Core)"
    ANSI_COLOR="0;31"
    CPE_NAME="cpe:/o:centos:centos:8"
    HOME_URL="https://www.centos.org/"
    BUG_REPORT_URL="https://bugs.centos.org/"
    
    CENTOS_MANTISBT_PROJECT="CentOS-8"
    CENTOS_MANTISBT_PROJECT_VERSION="8"
    REDHAT_SUPPORT_PRODUCT="centos"
    REDHAT_SUPPORT_PRODUCT_VERSION="8"
    

    安装:参考帮助文档 https://docs.docker.com/engine/install/centos/

    卸载旧的版本

    #卸载
    yum remove docker 
                      docker-client 
                      docker-client-latest 
                      docker-common 
                      docker-latest 
                      docker-latest-logrotate 
                      docker-logrotate 
                      docker-engine
                      
    #需要的安装包
    yum install -y yum-utils
    #设置镜像的仓库
    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
        
    #更新yum软件包索引
    yun makecache fast
        
    #安装docker  decker-ce社区版的 ee企业版
    yum install docker-ce docker-ce-cli containerd.io
    
    #启动docker
    systemctl start docker
    
    #查看是否安装成功
    docker version
    
    

    #启动 hello-world
    docker run hello-world
    

    #查看下载的hello-world镜像
    [root@zhourui /]# docker images
    REPOSITORY    TAG       IMAGE ID       CREATED       SIZE
    hello-world   latest    d1165f221234   2 weeks ago   13.3kB
    
    
    #卸载docker
    yum remove docker-ce docker-ce-cli containerd.io
    #删除资源
    rm -rf /var/lib/docker
    rm -rf /var/lib/containerd
    

    配置阿里云镜像加速

    登录阿里云找到容器服务。

    找到容器镜像服务

    配置使用

    sudo mkdir -p /etc/docker
    
    sudo tee /etc/docker/daemon.json <<-'EOF'
    {
      "registry-mirrors": ["https://tk46rux4.mirror.aliyuncs.com"]
    }
    EOF
    
    sudo systemctl daemon-reload
    
    sudo systemctl restart docker
    

    回顾helloworld流程

    流程图

    工作原理

    Docker是一个Client,Server结构的系统,Docker的守护进程运行在主机上,通过Socket从客户端访问。

    DockerServer接收到DockerClient的指令,就会执行这个命令。

    Docker为什么比VNM快:

    Docker有比虚拟机更少的抽象层。

    Docker利用的是宿主机的内核,VM有自己的Guest OS。

    新建一个容器的时候,Docker不需要像虚拟机一样新建一个系统内核。利用宿主机的内核,提升了启动速度和系统资源利用率。

    Docker的常用命令

    帮助命令

    docker -version    #显示docker的版本信息
    docker info		   #docker的详细信息 镜像和容器的数量
    docker 命令 --help  #万能命令
    docker --help		#docker的所有命令
    

    命令:官网地址 https://docs.docker.com/reference/

    镜像命令

    docker images:查看本机所有镜像

    [root@zhourui /]# docker images
    REPOSITORY    TAG       IMAGE ID       CREATED       SIZE
    hello-world   latest    d1165f221234   2 weeks ago   13.3kB
    
    #解释
    REPOSITORY 镜像的仓库源
    TAG			镜像的标签
    IMAGE ID	镜像的 id
    CREATED		镜像的创建时间
    SIZE		镜像的大小
    
    #可选项
      -a, --all             #显示所有的镜像
      -q, --quiet           #只显示镜像的id
    
    

    docker search:搜索镜像

    [root@zhourui /]# docker search mysql
    NAME                              DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
    mysql                             MySQL is a widely used, open-source relation…   10634     [OK]       
    mariadb                           MariaDB Server is a high performing open sou…   3990      [OK]       
    
    #可选项
    --filter=STARS=3000		#搜索出来的就是stars大于等于3000的  -f简写
    [root@zhourui /]# docker search mysql -f=STARS=3000
    NAME      DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
    mysql     MySQL is a widely used, open-source relation…   10634     [OK]       
    mariadb   MariaDB Server is a high performing open sou…   3990      [OK] 
    

    docker pull:下载镜像

    #下载 docker pull 镜像名 [:tag](可以选版本) 不写版本默认latest最后一个
    [root@zhourui /]# docker pull mysql
    Using default tag: latest
    latest: Pulling from library/mysql
    a076a628af6f: Pull complete 		#分层下载 docker image核心 联合文件系统 
    f6c208f3f991: Pull complete 
    88a9455a9165: Pull complete 
    406c9b8427c6: Pull complete 
    7c88599c0b25: Pull complete 
    25b5c6debdaf: Pull complete 
    43a5816f1617: Pull complete 
    1a8c919e89bf: Pull complete 
    9f3cf4bd1a07: Pull complete 
    80539cea118d: Pull complete 
    201b3cad54ce: Pull complete 
    944ba37e1c06: Pull complete 
    Digest: sha256:feada149cb8ff54eade1336da7c1d080c4a1c7ed82b5e320efb5beebed85ae8c	#签名
    Status: Downloaded newer image for mysql:latest		
    docker.io/library/mysql:latest		#真实地址
    
    # docker pull mysql
    # 等价
    # docker pull docker.io/library/mysql:latest
    
    #指定版本下载
    [root@zhourui /]# docker pull mysql:5.7
    5.7: Pulling from library/mysql
    a076a628af6f: Already exists 		#共用
    f6c208f3f991: Already exists 
    88a9455a9165: Already exists 
    406c9b8427c6: Already exists 
    7c88599c0b25: Already exists 
    25b5c6debdaf: Already exists 
    43a5816f1617: Already exists 
    1831ac1245f4: Pull complete 
    37677b8c1f79: Pull complete 
    27e4ac3b0f6e: Pull complete 
    7227baa8c445: Pull complete 
    Digest: sha256:b3d1eff023f698cd433695c9506171f0d08a8f92a0c8063c1a4d9db9a55808df
    Status: Downloaded newer image for mysql:5.7
    docker.io/library/mysql:5.7
    
    [root@zhourui /]# docker images
    REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
    hello-world   latest    d1165f221234   2 weeks ago    13.3kB
    mysql         5.7       a70d36bc331a   2 months ago   449MB
    mysql         latest    c8562eaf9d81   2 months ago   546MB
    

    docker rmi:删除镜像

    #删除指定的容器 根据id
    [root@zhourui /]# docker rmi -f c8562eaf9d81
    #删除多个镜像
    [root@zhourui /]# docker rmi -f id1 id2 id3
    #删除全部容器
    [root@zhourui /]# docker rmi -f $(docker images -aq)
    
    

    容器命令

    我们有了镜像才可以创建容器,下载一个CentOS镜像来测试学习。

    docker pull centos
    

    新建容器并启动

    docker run (可选参数) image
    
    #参数说明
    --name=“Name” 	#容器名字 tomcat01 tomcat01 来区分
    -d 				#后台方式运行
    -it 			#使用交互方式运行,进入容器查看内容
    -p 				#指定容器的端口 -p 8080:8080
    	-p 主机端口:容器端口 (常用)
    	-p ip:主机端口:容器端口
    	-p 容器端口
    	容器端口(不写-p)
    -p 				#随机指定端口
    
    #启动并进入容器
    [root@zhourui /]# docker run -it centos /bin/bash
    [root@b728c79b5448 /]# ls   #查看容器内的centos  基础版本 很多的命令不完善
    bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
    [root@b728c79b5448 /]# exit  #退出命令
    exit
    [root@zhourui /]# ls
    bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  patch  proc  root  run  sbin  srv  sys  tmp  usr  var  www
    
    

    列出所有运行的容器

    # docker ps  
    	#列出所有在运行的容器
    -a	#列出历史运行过的容器
    -n=? #显示最近创建的n个容器
    -q	#列出运行容器的id
    
    [root@zhourui /]# docker ps  
    CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
    [root@zhourui /]# docker ps -a
    CONTAINER ID   IMAGE          COMMAND       CREATED         STATUS                     PORTS     NAMES
    b728c79b5448   centos         "/bin/bash"   4 minutes ago   Exited (0) 2 minutes ago             relaxed_elbakyan
    0ce52f9209e4   d1165f221234   "/hello"      5 hours ago     Exited (0) 5 hours ago               intelligent_mirzakhani
    
    

    退出容器

    exit  #容器停止并退出
    ctrl +P +Q  #按住这三个键 容器不停止退出
    
    [root@zhourui /]# docker run -it centos /bin/bash
    [root@c9797d0b4ba8 /]# [root@zhourui /]# docker ps
    CONTAINER ID   IMAGE     COMMAND       CREATED              STATUS              PORTS     NAMES
    c9797d0b4ba8   centos    "/bin/bash"   About a minute ago   Up About a minute             inspiring_faraday
    
    

    删除容器

    docker rm 			#删指定id的容器  不能删除正在运行的容器  强制删除 rm -f
    docker rm -f $(docker ps -aq) #删除全部的容器
    docker -a-q|xargs docker rm   #删除全部容器
    

    启动和停止容器的操作

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

    常用其它命令

    后台启动容器

    # docker run -d 容器名  后台启动
    [root@zhourui /]# docker run -d centos
    #运行docker ps 发现centos停止了
    
    #docker容器使用后台运行,就必须有一个前台进程,docker发现没有应用,就会自动停止
    
    

    查看日志

    docker logs -f -t --tail 10 容器id #打印最近10条日志
    
    #编写shell脚本
    “while true;do echo zhourrrrr;sleep 1;done”
    
    [root@zhourui /]# docker run -d centos /bin/bash -c "while true;do echo zhourrrr;sleep 1;done"
    e79bac46e660abb781dcce7b0dbd3a3a896b573a104fdd9a15db0bbf5331341b
    [root@zhourui /]# docker ps
    CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS        PORTS     NAMES
    e79bac46e660   centos    "/bin/bash -c 'while…"   3 seconds ago   Up 1 second             jolly_sanderson
    
    #显示日志
    -tf  #显示日志 t 时间
    --tail number #最近的多少条数据
    [root@zhourui /]# docker logs -f -t --tail 10 e79bac46e660 
    

    查看容器中的进程信息

    docker top 容器id

    [root@zhourui /]# docker top e79bac46e660
    UID                 PID                 PPID                C                   STIME               TTY     
    root                227610              227588              0                   22:36               ?       
    root                229020              227610              0                   22:45               ?       
    

    查看镜像源数据

    docker inspect 容器id

    [root@zhourui /]# docker inspect e79bac46e660
    [
        {
            "Id": "e79bac46e660abb781dcce7b0dbd3a3a896b573a104fdd9a15db0bbf5331341b",
            "Created": "2021-03-21T14:36:07.740342428Z",
            "Path": "/bin/bash",
            "Args": [
                "-c",
                "while true;do echo zhourrrr;sleep 1;done"
            ],
            "State": {
                "Status": "running",
                "Running": true,
                "Paused": false,
                "Restarting": false,
                "OOMKilled": false,
                "Dead": false,
                "Pid": 227610,
                "ExitCode": 0,
                "Error": "",
                "StartedAt": "2021-03-21T14:36:08.2053845Z",
                "FinishedAt": "0001-01-01T00:00:00Z"
            },
            .........#省略...
         }
    }
    
    

    进入当前正在运行的容器

    #通常容器都是后台的方式运行的,需要进入容器修改一些配置
    #命令
    docker exec -it 容器id bashShell(bin/bash)
    #测试
    [root@zhourui /]# docker ps
    CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS     NAMES
    538cddb5e369   centos    "bin/bash -c 'while …"   14 seconds ago   Up 13 seconds             quizzical_wing
    [root@zhourui /]# docker exec -it 538cddb5e369 bin/bash
    [root@538cddb5e369 /]# 
    [root@538cddb5e369 /]# ls
    bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
    [root@538cddb5e369 /]# ps -ef
    UID          PID    PPID  C STIME TTY          TIME CMD
    root           1       0  0 11:08 ?        00:00:00 bin/bash -c while true;do echo zzzzzrr;sleep 2;done
    root          66       0  0 11:10 pts/0    00:00:00 bin/bash
    root         131       1  0 11:12 ?        00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 2
    root         132      66  0 11:12 pts/0    00:00:00 ps -ef
    
    #方式二
    docker attach 容器id
    #测试
    [root@zhourui /]# docker attach 538cddb5e369
    zzzzzrr
    zzzzzrr
    zzzzzrr
    zzzzzrr
    #进去后是正在执行的当前代码,想停止可以新开一个窗口 docker rm -f $(docker ps -aq)
    
    # docker exec  进入后打开了一个新的终端,可以在里面操作
    # docker attach 进入容器正在执行的终端,不会启动新的进程
    

    从容器内拷贝文件到主机上

    docker cp 容器id:容器内路径 目的主机路径
    #测试
    [root@zhourui /]# cd /home
    [root@zhourui home]# ls
    www  zhour.java
    [root@zhourui home]# docker ps
    CONTAINER ID   IMAGE     COMMAND       CREATED              STATUS              PORTS     NAMES
    44e87620bf99   centos    "/bin/bash"   About a minute ago   Up About a minute             romantic_burnell
    #进入容器
    [root@zhourui home]# docker attach 44e87620bf99
    [root@44e87620bf99 /]# cd /home
    [root@44e87620bf99 home]# ls
    #在容器内新建一个文件
    [root@44e87620bf99 home]# touch zr.java
    [root@44e87620bf99 home]# ls
    zr.java
    [root@44e87620bf99 home]# exit
    exit
    [root@zhourui home]# docker ps
    CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
    [root@zhourui home]# docker ps -a
    CONTAINER ID   IMAGE     COMMAND       CREATED         STATUS                     PORTS     NAMES
    44e87620bf99   centos    "/bin/bash"   3 minutes ago   Exited (0) 6 seconds ago             romantic_burnell
    
    #将容器内的文件拷贝到主机上
    [root@zhourui home]# docker cp 44e87620bf99:/home/zr.java /home
    [root@zhourui home]# ls
    www  zhour.java  zr.java
    [root@zhourui home]#
    
    #拷贝是一个手动过程,后面学习使用 -v 卷的技术,可以实现自动同步
    

    小结

    常用命令

    练习部署

    部署Nginx

    1. 搜索镜像:docker search nginx

    2. 下载镜像:docker pull nginx

    3. 运行测试:docker run -d --name nginx01 -p 3344:80 nginx (--name:起别名,-p 3344:80 3344是暴露的端口就是宿主机端口 80是nginx默认端口就是容器的端口)

      [root@zhourui home]# docker images
      REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
      nginx         latest    f6d0b4767a6c   2 months ago    133MB
      centos        latest    300e315adb2f   3 months ago    209MB
      hello-world   latest    bf756fb1ae65   14 months ago   13.3kB
      
      #--name:起别名,-p 3344:80 3344是暴露的端口 80是nginx默认端口
      [root@zhourui home]# docker run -d --name nginx01 -p 3344:80 nginx
      56b36ad955ca7cf6d80708b20d7ffd1152a0ca974c312df45bfe9e31d0888e0b
      [root@zhourui home]# docker ps
      CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                  NAMES
      56b36ad955ca   nginx     "/docker-entrypoint.…"   7 seconds ago   Up 6 seconds   0.0.0.0:3344->80/tcp   nginx01
      [root@zhourui home]# curl localhost:3344
      
      [root@zhourui home]# docker exec -it nginx01 bin/bash
      root@56b36ad955ca:/# whereis nginx
      nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx
      root@56b36ad955ca:/# cd /etc/nginx
      root@56b36ad955ca:/etc/nginx# ls
      conf.d	fastcgi_params	koi-utf  koi-win  mime.types  modules  nginx.conf  scgi_params	uwsgi_params  win-utf
      root@56b36ad955ca:/etc/nginx# 
      #每次改动nginx的配置文件,都需要进入容器的内部修改,非常麻烦,后面学习数据卷的技术就可以在容器外部修改文件,容器内自动同步。
      

      访问自己服务器的nginx:http://39.105.48.232:3344/(前提是自己阿里云服务器安全组中开启了3344端口)

    部署Tomcat

    #docker hub 官方的使用
    docker run -it --rm tomcat:9.0
    #之前练习的启动在后台,停止容器后,容器还在,可以查到。run -it --rm 一般用来测试,用完即删除(容器删除镜像还在)
    [root@zhourui /]# docker pull tomcat
    
    [root@zhourui /]# docker images
    REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
    tomcat        9.0       040bdb29ab37   2 months ago    649MB
    tomcat        latest    040bdb29ab37   2 months ago    649MB
    nginx         latest    f6d0b4767a6c   2 months ago    133MB
    centos        latest    300e315adb2f   3 months ago    209MB
    hello-world   latest    bf756fb1ae65   14 months ago   13.3kB
    [root@zhourui /]# docker run -d -p 3355:8080 --name tomcat01 tomcat
    53197d7745a2d7f83f3a45b1f474a189eb7f496b0cf08c9a509a6c390680e347
    [root@zhourui /]# curl localhost:3355
    
    

    浏览器测试访问:http://39.105.48.232:3355/(阿里云安全组开启端口),可以访问但是显示404。

    #进入容器
    [root@zhourui /]# docker exec -it tomcat01 /bin/bash
    root@53197d7745a2:/usr/local/tomcat# ls
    BUILDING.txt  CONTRIBUTING.md  LICENSE	NOTICE	README.md  RELEASE-NOTES  RUNNING.txt  bin  conf  lib  logs  native-jni-lib  temp  webapps  webapps.dist  work
    root@53197d7745a2:/usr/local/tomcat# cd webapps
    root@53197d7745a2:/usr/local/tomcat/webapps# ls
    root@53197d7745a2:/usr/local/tomcat/webapps# 
    #发现ll无法使用,ls-al可以使用,命令少了。webapps中是空的,默认的是最小的镜像,不必要的被删除了,保证的是最小可用环境。
    

    如果想要访问,可以复制webapps.dist目录的内容到webapps中

    root@53197d7745a2:/usr/local/tomcat/webapps# cd ..
    root@53197d7745a2:/usr/local/tomcat# cd webapps.dist
    root@53197d7745a2:/usr/local/tomcat/webapps.dist# ls
    ROOT  docs  examples  host-manager  manager
    root@53197d7745a2:/usr/local/tomcat/webapps.dist# cd ..
    root@53197d7745a2:/usr/local/tomcat# cp -r webapps.dist/* webapps
    root@53197d7745a2:/usr/local/tomcat# cd webapps
    root@53197d7745a2:/usr/local/tomcat/webapps# ls
    ROOT  docs  examples  host-manager  manager
    root@53197d7745a2:/usr/local/tomcat/webapps# 
    
    

    再次刷新网页访问即可!

    部署es+kibana

    #es暴漏的端口十分多
    #es十分耗内存
    #es的数据一般需要放置到安全目录,挂载。
    #--net somenetwork  网络配置
    
    #启动(启动前停掉其它的容器,防止启动不了)
    docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2
    
    #docker stats 容器id 查看cpu的状态
    #启动后 发现执行docker ps命令非常卡,因为内存快耗尽。
    

    启动后可以从宝塔上看到自己服务器的内存状态。(也可以使用命令docker stats 容器id 查看cpu,内存的状态)

    停掉es

    [root@zhourui /]# docker ps
    CONTAINER ID   IMAGE                 COMMAND                  CREATED         STATUS         PORTS                                            NAMES
    94c6cad2a01d   elasticsearch:7.6.2   "/usr/local/bin/dock…"   5 minutes ago   Up 5 minutes   0.0.0.0:9200->9200/tcp, 0.0.0.0:9300->9300/tcp   elasticsearch
    [root@zhourui /]# docker stop 94c6cad2a01d
    94c6cad2a01d
    
    

    这时查看服务器的状态

    再次启动,增加内存的配置,修改配置文件,-e 环境配置修改。

    docker run -d --name elasticsearch02 -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 9222:9000 
    --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
    
    • Rancher(CI/CD 持续集成/持续部署时使用)

    启动portainer后访问测试:http://39.105.48.232:9222/,密码可以随意输入。

    进入后选择local,点击connect

    可以看到镜像,容器等

    查看镜像

    Docker镜像

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

    将应用直接打包为docker镜像,就可以直接跑起来。

    如何得到镜像:

    • 从仓库下载
    • 自己制作一个镜像

    Docker镜像加载原理

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

    可以使用docker images看到Centos的镜像非常小。

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

    分层理解

    下载一个镜像,观察日志输出,可以看到是一层一层的在下载(分层下载,提高了复用性)

    使用docker inspect redis,可以看到RootFS

     "RootFS": {
                "Type": "layers",
                "Layers": [
                    "sha256:cb42413394c4059335228c137fe884ff3ab8946a014014309676c25e3ac86864",
                    "sha256:8e14cb7841faede6e42ab797f915c329c22f3b39026f8338c4c75de26e5d4e82",
                    "sha256:1450b8f0019c829e638ab5c1f3c2674d117517669e41dd2d0409a668e0807e96",
                    "sha256:f927192cc30cb53065dc266f78ff12dc06651d6eb84088e82be2d98ac47d42a0",
                    "sha256:a24a292d018421783c491bc72f6601908cb844b17427bac92f0a22f5fd809665",
                    "sha256:3480f9cdd491225670e9899786128ffe47054b0a5d54c48f6b10623d2f340632"
                ]
            },
    

    理解:所有的Docker镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,都会在当前的镜像层上,创建新的镜像层。在添加额外的镜像层时,镜像始终保持是当前所有镜像的组合。

    特点:

    docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部。这一层通常是我们所说的容器层,容器之下都是镜像层。

    commit镜像

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

    测试

    #启动一个tomcat
    docker run -it -p 8081:8080 tomcat
    
    #在新的窗口进入tomcat
    [root@zhourui /]# docker ps
    CONTAINER ID   IMAGE                 COMMAND                  CREATED          STATUS          PORTS          1fd9b7b4cb3d   tomcat                "catalina.sh run"        28 seconds ago   Up 27 seconds   0.0.0.0:8081->8080/tcp                           
    [root@zhourui /]# docker exec -it 1fd9b7b4cb3d /bin/bash
    
    #官方默认的tomcat的webapps下面没有应用,自己拷贝
    cp -r webapps.dist/* webapps
    
    #提交自己的镜像,以后使用修改过的镜像即可
    [root@zhourui /]# docker commit -a="zhourr" -m="add webapps" 1fd9b7b4cb3d tomcat02:1.0
    sha256:1c7804b415ba38099178f63e48444aebec938252632defd16bb35acc71bdabab
    [root@zhourui /]# docker images
    REPOSITORY            TAG       IMAGE ID       CREATED         SIZE
    tomcat02              1.0       1c7804b415ba   6 seconds ago   654MB
    redis                 latest    621ceef7494a   2 months ago    104MB
    tomcat                9.0       040bdb29ab37   2 months ago    649MB
    tomcat                latest    040bdb29ab37   2 months ago    649MB
    nginx                 latest    f6d0b4767a6c   2 months ago    133MB
    centos                latest    300e315adb2f   3 months ago    209MB
    portainer/portainer   latest    62771b0b9b09   8 months ago    79.1MB
    elasticsearch         7.6.2     f29a1ee41030   12 months ago   791MB
    hello-world           latest    bf756fb1ae65   14 months ago   13.3kB
    [root@zhourui /]# 
    
    

    对容器进行修改后,想保存容器的状态,通过commit来提交,下次就可以使用自己提交的这个镜像了。就好比 vm 的快照功能。

    容器数据卷

    如果数据在容器中,那么将容器删除,数据就会丢失!需求,数据可持久化!!

    MySQL容器删除,数据丢失,需求,MySQL数据可以存储在本地!!

    容器之间可以有一个数据共享的技术。Docker容器中产生的数据,同步到本地。

    这就是卷技术!将容器内的目录,挂载到主机上。

    数据持久化和同步操作,容器间也是可以数据共享的。

    使用数据卷

    方式一:使用命令来挂载 -v

    docker -it -v主机内的目录:容器内的目录
    #测试
    [root@zhourui home]# docker run -it -v /home/zrtest:/home centos /bin/bash
    
    #启动后使用 docker inspect 容器id 查看
    

    使用 docker inspect 容器id 查看

    测试文件的同步

    1.停止容器

    2.修改宿主机上的文件

    3.启动容器,发现文件依旧是同步的

    好处:以后修改只需要在本地修改即可,不需要进入容器!

    部署MySQL

    MySQL的数据持久化问题!

    #获取镜像
    docker pull mysql:5.7
    
    #运行容器,数据挂载。安装mysql需要配置密码的,注意!
    #官方测试连接方法
    docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
    
    #启动MySQL
    -d:后台运行
    -p:端口映射
    -v:数据卷挂载
    -e:环境配置
    --name:容器别名
    docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
    
    #在本地连接上后创建一个test数据库,查看映射路径是否可以。
    

    在本地使用Navicat测试连接

    将容器删除后

    [root@zhourui data]# ls
    auto.cnf    ca.pem           client-key.pem  ibdata1      ib_logfile1  mysql               private_key.pem  server-cert.pem  sys
    ca-key.pem  client-cert.pem  ib_buffer_pool  ib_logfile0  ibtmp1       performance_schema  public_key.pem   server-key.pem   test
    

    可以看到test数据库还在,即挂载到本地的数据卷没有丢失,这就实现了容器数据的持久化。

    具名挂载和匿名挂载

    #匿名挂载
    -P(大写P 随机映射端口)
    -v 容器内路径
    docker run -d -P --name nginx01 -v /etc/nginx nginx
    
    #查看所有的卷的情况
    [root@zhourui home]# docker volume ls
    DRIVER    VOLUME NAME
    local     42a60ffb1a9dfcefffdf269e3a08fcb9172a082babe6ea19b864d5f679eb4361
    local     93e2f2060025965b83b0433b95e29ac325c25fa8684b79a12617438ffe898941
    local     271ccfa1da7814fa8fceb5b482ce86009f97e29c09dca69bcc594a0d8fabb92a
    
    #匿名挂载:这里-v的时候只写了容器内的路径,没有写容器外的路径
    
    #具名挂载
    [root@zhourui home]# docker  run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
    3024685007a57eda45820c8c07920cea08b84b7847b86fd97f5f71f7100b8fbd
    [root@zhourui home]# docker volume ls
    DRIVER    VOLUME NAME
    local     42a60ffb1a9dfcefffdf269e3a08fcb9172a082babe6ea19b864d5f679eb4361
    local     93e2f2060025965b83b0433b95e29ac325c25fa8684b79a12617438ffe898941
    local     271ccfa1da7814fa8fceb5b482ce86009f97e29c09dca69bcc594a0d8fabb92a
    local     juming-nginx
    [root@zhourui home]# 
    
    #通过-v 卷名:容器内名字
    #查看卷
    [root@zhourui home]# 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,就说明这个文件只能通过宿主机来操作,容器内部是无法操作的!
    

    初识Dockerfile

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

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

    方式二:

    [root@zhourui home]# pwd
    /home
    [root@zhourui home]# cd docker-test-volume/
    [root@zhourui docker-test-volume]# pwd
    /home/docker-test-volume
    [root@zhourui docker-test-volume]# vim dockerfile  #创建dockerfile
    [root@zhourui docker-test-volume]# cat dockerfile  #文件中添加以下内容后查看(文件中内容 指令(大写) 参数)
    #每个命令就是镜像的一层
    FROM centos
    
    VOLUME ["volume01","volume02"]  #匿名挂载
    
    CMD echo "....end...."
    CMD /bin/bash
    
    [root@zhourui docker-test-volume]# docker build -f /home/docker-test-volume/dockerfile -t zhour/centos:1.0 .
    
    

    #启动自己生成的容器
    docker run -it 29e054de9dd4 /bin/bash
    #在volume01中创建文件
    [root@e224b7ebc0d7 volume01]# ls
    [root@e224b7ebc0d7 volume01]# touch container.txt
    [root@e224b7ebc0d7 volume01]# ls
    container.txt
    [root@e224b7ebc0d7 volume01]# 
    
    

    查看匿名卷挂载的路径:docker inspect 容器id

    进入挂载的路径中查看

    [root@zhourui /]# cd /var/lib/docker/volumes/f517ef934bb1d4376751cf0ec11608ed0fd287844436ba62cad973ce0f67dee8/_data
    [root@zhourui _data]# ls
    container.txt
    [root@zhourui _data]# 
    
    

    可以看到文件已经同步!!

    这种方式较常使用,通常用于构建自己的镜像。

    假设构建镜像时没有挂载卷,需要手动挂载,-v 卷名:容器内路径。

    数据卷容器

    启动三个容器

    #创建docker01
    [root@zhourui /]# docker run -it --name docker01 29e054de9dd4
    [root@255f9d13bea7 /]# ls
    bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var  volume01	volume02
    
    #创建docker02
    [root@zhourui /]# docker run -it --name docker02 --volumes-from docker01 29e054de9dd4
    [root@861b5d25a8ca /]# ls
    bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var  volume01	volume02
    
    #在docker01的volume01中创建文件
    [root@zhourui /]# docker attach 255f9d13bea7
    [root@255f9d13bea7 /]# cd volume01
    [root@255f9d13bea7 volume01]# ls
    [root@255f9d13bea7 volume01]# touch docker01
    
    #进入docker02的volume01中查看
    [root@861b5d25a8ca /]# cd volume01
    [root@861b5d25a8ca volume01]# ls
    docker01
    
    #创建docker03并在volume01中增加docker03文件
    [root@zhourui /]# docker run -it --name docker03 --volumes-from docker01 29e054de9dd4
    [root@7a405584084a /]# cd volume01
    [root@7a405584084a volume01]# ls
    docker01
    [root@7a405584084a volume01]# touch docker03
    [root@7a405584084a volume01]# ls
    docker01  docker03
    
    #在docker01中查看volume01
    [root@255f9d13bea7 volume01]# ls
    docker01  docker03
    [root@255f9d13bea7 volume01]# 
    
    

    通过 --volumes-from 可以实现容器间的数据共享!!

    可以测试删除掉 docker01 ,再去查看 docker02 和 docker03 ,数据仍然还在。

    三个容器之间的文件是相互拷贝的,删掉一个不会丢失数据。

    应用:多个 MySQL 或者 Redis 之间实现数据共享!!

    docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
    
    docker run -d -p 3310:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01 mysql:5.7
    #可以实现两个MySQL之间的数据同步
    

    结论:容器之间配置信息的传递,数据卷容器的生命周期是一直持续到没有容器使用为止。

    通过 -v 将数据持久化到本地,本地的数据是不会删除的。

    DockerFile

    DockerFile介绍

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

    构建步骤:

    1. 编写一个 dockerfile 文件
    2. docker build 构建成为一个镜像
    3. docker run 运行镜像
    4. docker push 发布镜像(dockerHub,阿里云镜像仓库)

    查看官方 centos,点击版本会跳转至 GitHUb

    很多的官方镜像都是基础包,一些功能没有,我们就需要自己搭建。

    DockerFile构建过程

    基础知识:

    1. 每个保留关键字(指令)必须是大写字母。
    2. 只需顺序从上到下。
    3. , 表示注释。

    4. 每个指令都会创建提交一个新的镜像层。

    docker 是面向开发的,发布项目做镜像,就需要编写 dockerfile 文件。

    Docker镜像逐渐成为企业交付的标准。

    dockerfile :构建文件,定义了一切所需的环境和源代码。

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

    docker 容器:容器是镜像运行起来后提供服务的。

    DockerFile指令

    FROM		#基础镜像,一切从这里开始构建
    MAINTAINER	#镜像是谁写的
    RUN			#docker 镜像构建的时候需要运行的命令
    ADD			#步骤:使用tomcat镜像,tomcat压缩包,就是添加的内容
    WORKDIR		#镜像的工作目录
    VOLUME		#挂载的目录位置
    EXPOSE		#暴漏端口配置
    CMD 		#指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
    ENTRYPOINT	#指定这个容器启动的时候要运行的命令,可以追加命令
    ONBUILD		#当构建一个被继承的 dockerfile 这个时候会运行 ONBUILD 的指令,触发指令
    COPY		#类似add命令,将文件拷贝拷贝到目录中
    ENV			#构建的时候设置环境变量
    

    实战测试

    Docker Hub 中99%的镜像都是由这个基础镜像 FROM scratch 来配置构建的

    FROM scratch
    ADD centos-8-x86_64.tar.xz /
    LABEL 
    	org.label-schema.schema-version="1.0" 
        org.label-schema.name="CentOS Base Image" 
        org.label-schema.vendor="CentOS" 
        org.label-schema.license="GPLv2"  
        org.label-schema.build-date="20201204"
    CMD ["/bin/bash"]
    

    创建一个自己的 CentOS

    #编写 dockerfile 的文件
    [root@zhourui home]# cd dockerfile/
    [root@zhourui dockerfile]# ls
    [root@zhourui dockerfile]# vim mydockerfile-centos
    [root@zhourui dockerfile]# cat mydockerfile-centos 
    FROM centos
    MAINTAINER zhourr<813794474@qq.com>
    
    ENV MYPATH /usr/local
    WORKDIR $MYPATH  	#进去后的工作目录,进去后 pwd 查看
    
    RUN yum -y install vim  	#安装 vim
    RUN yum -y install net-tools  #安装后可以使用 ifconfig (不安装只能用 ip add)
    
    EXPOSE 80
    
    CMD echo $MYPATH
    CMD echo "...end..."
    CMD /bin/bash
    
    #通过这个文件构建镜像
    -f 构建文件路径
    -t 镜像名:[tag]
    最后有个 .
    [root@zhourui dockerfile]# docker build  -f mydockerfile-centos -t mycentos:0.1 .
    ...
    Successfully built ddba7ccc7eee
    Successfully tagged mycentos:0.1
    
    #测试运行
    docker run -it mycentos:0.1
    
    

    默认的 centos 以下命令无法使用

    [root@95c725dda358 /]# pwd
    /
    [root@95c725dda358 /]# vim
    bash: vim: command not found
    [root@95c725dda358 /]# ifconfig
    bash: ifconfig: command not found
    [root@95c725dda358 /]# 
    

    测试运行自己创建的镜像这些命令就可以使用了。

    我们可以列出本地镜像的变更历史 docker history 镜像id

    CMD和ENTRYPOINT的区别

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

    测试 CMD

    [root@zhourui dockerfile]# vim dockerfile-cmd-test
    FROM centos
    CMD ["ls","-a"]
    
    #构建镜像
    [root@zhourui dockerfile]# docker build -f dockerfile-cmd-test -t cmdtest .
    ....
    Successfully built a44c7103184f
    Successfully tagged cmdtest:latest
    # run 运行,可以看到 ls-a 命令生效
    [root@zhourui dockerfile]# docker run a44c7103184f
    .
    ..
    .dockerenv
    bin
    dev
    etc
    home
    lib
    ...
    
    #追加一个 l ,希望返回 ls-al
    [root@zhourui dockerfile]# docker run a44c7103184f -l
    docker: Error response from daemon: OCI runtime create failed: container_linux.go:367: starting container process caused: exec: "-l": executable file not found in $PATH: unknown.
    
    #此时报错,因为使用CMD,-l替换了["ls","-a"],-l不是命令,所以报错
    #需要使用以下完整命令
    [root@zhourui dockerfile]# docker run a44c7103184f ls -al
    
    

    测试 ENTRYPOINT

    [root@zhourui dockerfile]# vim dockerfile-entrypoint
    FROM centos
    ENTRYPOINT ["ls","-a"]
    
    [root@zhourui dockerfile]# docker build -f dockerfile-entrypoint -t entrypointtest .
    ...
    Successfully built 34773b8b0398
    Successfully tagged entrypointtest:latest
    [root@zhourui dockerfile]# docker run 34773b8b0398
    .
    ..
    .dockerenv
    bin
    dev
    etc
    home
    lib
    ...
    # 添加 -l,是可以直接追加到后面的,ls -a -l
    [root@zhourui dockerfile]# docker run 34773b8b0398 -l
    total 0
    drwxr-xr-x   1 root root   6 Mar 27 14:51 .
    drwxr-xr-x   1 root root   6 Mar 27 14:51 ..
    -rwxr-xr-x   1 root root   0 Mar 27 14:51 .dockerenv
    lrwxrwxrwx   1 root root   7 Nov  3 15:22 bin -> usr/bin
    drwxr-xr-x   5 root root 340 Mar 27 14:51 dev
    drwxr-xr-x   1 root root  66 Mar 27 14:51 etc
    drwxr-xr-x   2 root root   6 Nov  3 15:22 home
    lrwxrwxrwx   1 root root   7 Nov  3 15:22 lib -> usr/lib
    
    

    Docker中很多命令都十分相似,需要去对比测试一下,才能发现其中的区别。

    实战 Tomcat镜像

    1. 准备镜像文件 tomcat 压缩包,jdk压缩包(放到home/zhour-tar目录下)

    2. 编写 Dockerfile 文件,官方命名:Dockerfile,build的时候会自动寻找这个文件,就不需要 -f 指定了。(在home/zhour-tar目录下,vim Dockerfile),压缩包会自动解压。

      FROM centos
      MAINTAINER zhourr<813794474@qq.com>
      
      COPY readme.txt /usr/local/read.txt
      
      ADD jdk-8u281-linux-x64.tar.gz /usr/local/
      ADD apache-tomcat-9.0.44.tar.gz /usr/local/
      
      RUN yum -y install vim
      
      ENV MYPATH /usr/local
      WORKDIR $MYPATH
      
      ENV JAVA_HOME /usr/local/jdk1.8.0_281
      ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
      ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.44
      ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.44
      ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
      
      EXPOSE 8080
      
      CMD /usr/local/apache-tomcat-9.0.44/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.44/bin/logs/catalina.out
      
      
    3. 构建镜像

      [root@zhourui zhour-tar]# ls
      apache-tomcat-9.0.44.tar.gz  Dockerfile  jdk-8u281-linux-x64.tar.gz  readme.txt
      #构建
      [root@zhourui zhour-tar]# docker build -t diytomcat .
      
      
    4. 启动镜像

      [root@zhourui zhour-tar]# docker run -d -p 3030:8080 --name zhoutomcat -v /home/zhour-tar/test:/usr/local/apache-tomcat-9.0.44/webapps/test -v /home/zhour-tar/tomcatlogs/:/usr/local/apache-tomcat-9.0.44/logs diytomcat
      
      
    5. 访问测试

    6. 发布项目(配置了数据卷挂载,直接在容器外编写项目就可以发布了)在test中新建

      web.xml

      <?xml version="1.0" encoding="UTF-8"?>
      <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xmlns="http://java.sun.com/xml/ns/javaee"
               xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
               http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
               id="WebApp_ID" version="3.0">
       </web-app>
      

      index.jsp

      <%@ page language="java" contentType="text/html; charset=UTF-8"
          pageEncoding="UTF-8"%>
      <!DOCTYPE html>
      <html>
      <head>
      <meta charset="utf-8">
      <title>Hello zhourrr!!</title>
      </head>
      <body>
      Hello World!<br/>
      <%
      System.out.println("----my tomcat test----");
      %>
      </body>
      </html>
      
    7. 访问http://39.105.48.232:3030/test/

    8. 日志查看,cd /home/zhour-tar/tomcatlogs。cat catalina.out

    需要掌握 Dockersfile 的编写!!

    发布镜像

    在 Docker Hub 上注册账号,在服务器登录后就可以提交自己的镜像了。

    [root@zhourui tomcatlogs]# docker login --help
    
    Usage:  docker login [OPTIONS] [SERVER]
    
    Log in to a Docker registry.
    If no server is specified, the default is defined by the daemon.
    
    Options:
      -p, --password string   Password
          --password-stdin    Take the password from stdin
      -u, --username string   Username
    

    登录

    [root@zhourui tomcatlogs]# docker login -u zhourui88
    Password: 
    WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
    Configure a credential helper to remove this warning. See
    https://docs.docker.com/engine/reference/commandline/login/#credentials-store
    
    Login Succeeded
    
    

    提交

    [root@zhourui tomcatlogs]# docker push diytomcat
    Using default tag: latest
    The push refers to repository [docker.io/library/diytomcat]
    e21bfbb06ee5: Preparing 
    145f6d70801c: Preparing 
    f3ba2f2219d6: Preparing 
    f83a7c49f1e3: Preparing 
    2653d992f4ef: Preparing 
    denied: requested access to the resource is denied #拒绝
    #需要增加一个tag
    [root@zhourui tomcatlogs]# docker tag ea84d80641b1 zhourui88/tomcat:1.0
    #查看
    [root@zhourui tomcatlogs]# docker images
    REPOSITORY            TAG       IMAGE ID       CREATED             SIZE
    diytomcat             latest    ea84d80641b1   About an hour ago   640MB
    zhourui88/tomcat        1.0       ea84d80641b1   About an hour ago   640MB
    #提交
    [root@zhourui tomcatlogs]# docker push zhourui88/tomcat:1.0
    
    

    提交的时候镜像也是按层级来提交的!

    阿里云服务器

    1. 登录阿里云

    2. 找到容器镜像服务

    3. 创建命名空间

    4. 创建容器镜像

    5. 点击镜像仓库名 zhourui-test 浏览阿里云

    #登录
    [root@zhourui /]#  sudo docker login --username=周锐822 registry.cn-beijing.aliyuncs.com
    #提交到阿里云,这里没有更改tag,显示上传成功,但是我没有找到镜像
    [root@zhourui /]# docker push zhourui88/tomcat:1.0
    The push refers to repository [docker.io/zhourui88/tomcat]
    e21bfbb06ee5: Layer already exists 
    145f6d70801c: Layer already exists 
    f3ba2f2219d6: Pushing [==========>                                        ]  77.66MB/356.6MB
    f83a7c49f1e3: Layer already exists 
    
    #上传阿里云
    [root@zhourui /]# sudo docker tag ea84d80641b1 registry.cn-beijing.aliyuncs.com/docker-zhourui/zhourui-test:1.0
    [root@zhourui /]# docker images
    REPOSITORY                                                     TAG       IMAGE ID       CREATED        
    diytomcat                                                      latest    ea84d80641b1   3 hours ago         
    zhourui88/tomcat                                               1.0       ea84d80641b1   3 hours ago     
    registry.cn-beijing.aliyuncs.com/docker-zhourui/zhourui-test   1.0       ea84d80641b1   3 hours ago     
    [root@zhourui /]# docker push registry.cn-beijing.aliyuncs.com/docker-zhourui/zhourui-test:1.0
    
    

    上传后查看

    小结

    Docker网络

    理解 Dockers0

    ip addr

    #启动容器
    [root@zhourui /]# docker run -d -P --name tomcat01 tomcat
    72dee6c91e3f593c69858191014b9d228c6494b0aa049cd1f620350c1c46cd56
    #查看容器内部网络地址  eth0@if123 ip地址 docker分配的
    [root@zhourui /]# docker exec -it tomcat01 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
    122: eth0@if123: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
        link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
        inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
           valid_lft forever preferred_lft forever
    
    #Linux去ping容器的内部
    [root@zhourui /]# ping 172.17.0.2
    PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
    64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.062 ms
    64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.045 ms
    
    

    原理:我们每启动一个 docker 容器,docker就会给docker容器分配一个ip,我们只要安装了docker,就会有一个网卡docker0.

    桥接模式,使用的技术是 evth-pair 技术

    这时再输入 ip addr,发现多了一个网卡

    再启动一个 tomcat02 发现又多了一个网卡 (docker run -d -P --name tomcat02 tomcat) ipaddr

    查看tomcat02 ip addr

    [root@zhourui /]# docker exec -it tomcat02 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
    124: eth0@if125: <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
    

    可以发现容器的网卡都是一对一对的,【122: eth0@if123】【124: eth0@if125】。

    evth-pair:就是一对虚拟设备接口,它们都是成对出现的,一段连着协议,一段彼此相连。

    所以,evth-pair就充当一个桥梁,连接各种虚拟网络设备。

    测试tomcat01和tomcat02之间能不能ping通:

    [root@zhourui /]# docker exec -it tomcat02 ping 172.17.0.2
    PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
    64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.091 ms
    64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.069 ms
    #可以看到,容器之间是可以通信的
    

    流程图理解

    tomcat01 和 tomcat02 是公用一个路由器 docker0 。

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

    Docker使用的是 Linux 的桥接,宿主机中是 Docker 容器的网桥(Docker0)

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

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

    docker network ls,docker network inspect (桥接network id)可以查看

    假设我们想通过容器的名字来ping,而不是通过ip,就需要使用 --link。

    [root@zhourui /]# docker exec -it tomcat02 ping tomcat01
    ping: tomcat01: Name or service not known
    
    #通过--link可以解决
    [root@zhourui /]# docker run -d -P --name tomcat03 --link tomcat02 tomcat
    131bbb6e180687ff284ef2cabc78f4104dfc5d1018ee1e2f11a5b6e192bdc8bb
    [root@zhourui /]# docker exec -it tomcat03 ping tomcat02
    PING tomcat02 (172.17.0.3) 56(84) bytes of data.
    64 bytes from tomcat02 (172.17.0.3): icmp_seq=1 ttl=64 time=0.101 ms
    
    #反向ping
    [root@zhourui /]# docker exec -it tomcat02 ping tomcat03
    ping: tomcat03: Name or service not known
    
    

    docker network ls,docker network inspect (桥接network id)可以查看

    --link 使用后,tomcat03在本地配置了tomcat02

    [root@zhourui /]# docker exec -it tomcat03 cat /etc/hosts
    127.0.0.1	localhost
    ::1	localhost ip6-localhost ip6-loopback
    fe00::0	ip6-localnet
    ff00::0	ip6-mcastprefix
    ff02::1	ip6-allnodes
    ff02::2	ip6-allrouters
    172.17.0.3	tomcat02 1fff64acaf04
    172.17.0.4	131bbb6e1806
    

    本质:在hosts的配置中增加了 tomcat02 的映射。

    真实开发中,已经不建议使用 --link 了。

    自定义网络,不使用 docker0。docker0不支持容器名连接访问。

    自定义网络

    查看所有的docker网络

    [root@zhourui /]# docker network ls
    NETWORK ID     NAME      DRIVER    SCOPE
    25000c3be4a4   bridge    bridge    local  #桥接
    b518cb3beba9   host      host      local
    bcd06ce03d47   none      null      local
    

    网络模式

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

    none:不配置网络

    host:和宿主机共享网络

    container:容器内网络联通(局限性很大)

    测试:

    #直接启动,默认是 --net bridge 的,
    docker run -d -P --name tomcat01 tomcat
    docker run -d -P --name tomcat01 --net bridge tomcat
    
    #docker0特点,默认,域名不能访问,--link可以打通连接
    
    #自定义网络
    # --driver bridge
    # --subnet 192.168.0.0/16 
    # --gateway 192.168.0.1 
    [root@zhourui /]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
    6219f386e2bfc7f837554de2b011ec1d649d6eaafa617fcf4bdd2d8091cf82b2
    [root@zhourui /]# docker network ls
    NETWORK ID     NAME      DRIVER    SCOPE
    25000c3be4a4   bridge    bridge    local
    b518cb3beba9   host      host      local
    6219f386e2bf   mynet     bridge    local
    bcd06ce03d47   none      null      local
    
    

    查看自己的网络:docker network inspect mynet

    创建两个容器,连上自己的网络

    [root@zhourui /]# docker run -d -P --name tomcat-net-01 --net mynet tomcat
    c638c0cee8dff978e60532b9a1ddac74f10a45bfb6b542bf3fd3079f69ec5515
    [root@zhourui /]# docker run -d -P --name tomcat-net-02 --net mynet tomcat
    e9aee8d922b19af82f02e9e50b28a301ab10e7eb57828c454cb57b9ac5bdc0ae
    [root@zhourui /]# docker network inspect mynet
    [
        {
            "Name": "mynet",
            "Id": "6219f386e2bfc7f837554de2b011ec1d649d6eaafa617fcf4bdd2d8091cf82b2",
            "Created": "2021-03-28T17:29:39.571024726+08:00",
            "Scope": "local",
            "Driver": "bridge",
            "EnableIPv6": false,
            "IPAM": {
                "Driver": "default",
                "Options": {},
                "Config": [
                    {
                        "Subnet": "192.168.0.0/16",
                        "Gateway": "192.168.0.1"
                    }
                ]
            },
            "Internal": false,
            "Attachable": false,
            "Ingress": false,
            "ConfigFrom": {
                "Network": ""
            },
            "ConfigOnly": false,
            "Containers": {
                "c638c0cee8dff978e60532b9a1ddac74f10a45bfb6b542bf3fd3079f69ec5515": {
                    "Name": "tomcat-net-01",
                    "EndpointID": "6d4ac08b616e2e33e8fb7a3e8659b5a6ff2e381083572dbe202f7b8598347177",
                    "MacAddress": "02:42:c0:a8:00:02",
                    "IPv4Address": "192.168.0.2/16",
                    "IPv6Address": ""
                },
                "e9aee8d922b19af82f02e9e50b28a301ab10e7eb57828c454cb57b9ac5bdc0ae": {
                    "Name": "tomcat-net-02",
                    "EndpointID": "187733df51f17912e402211643ce7136cbb725d85a0c1045ef7e903471d9f878",
                    "MacAddress": "02:42:c0:a8:00:03",
                    "IPv4Address": "192.168.0.3/16",
                    "IPv6Address": ""
                }
            },
            "Options": {},
            "Labels": {}
        }
    ]
    
    #再次测试 ping 连接
    [root@zhourui /]# docker exec -it tomcat-net-01 ping 192.168.0.3
    PING 192.168.0.3 (192.168.0.3) 56(84) bytes of data.
    64 bytes from 192.168.0.3: icmp_seq=1 ttl=64 time=0.115 ms
    64 bytes from 192.168.0.3: icmp_seq=2 ttl=64 time=0.067 ms
    64 bytes from 192.168.0.3: icmp_seq=3 ttl=64 time=0.068 ms
    ^C
    --- 192.168.0.3 ping statistics ---
    3 packets transmitted, 3 received, 0% packet loss, time 67ms
    rtt min/avg/max/mdev = 0.067/0.083/0.115/0.023 ms
    
    #不使用 --link。也可以ping名字了
    [root@zhourui /]# docker exec -it tomcat-net-01 ping tomcat-net-02
    PING tomcat-net-02 (192.168.0.3) 56(84) bytes of data.
    64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.075 ms
    64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.070 ms
    64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=3 ttl=64 time=0.086 ms
    
    

    自定义的网络donker帮我们维护好了关系,推荐使用自定义的网络。

    应用:
    redis:不同的集群使用不同的网络,保证集群是安全和健康的(192.168.xxx.xxx)

    mysql:不同的集群使用不同的网络,保证集群是安全和健康的(192.182.xxx.xxx)

    网络联通

    创建两个容器在默认的docker0网络下

    [root@zhourui /]# docker run -d -P --name tomcat01 tomcat
    [root@zhourui /]# docker run -d -P --name tomcat02 tomcat
    

    现在就有以下的四个容器在在 docker0 和 mynet 网络下。怎样去打通 tomcat01 连接到 mynet。

    通过 --help 查看命令

    测试打通 tomcat01 连接到 mynet

    [root@zhourui /]# docker network connect mynet tomcat01
    [root@zhourui /]# docker network inspect mynet
    
    #打通之后,tomcat01被放到了 mynet 网络下,
    #一个容器两个 ip 地址
    

    测试

    [root@zhourui /]# docker exec -it tomcat01 ping tomcat-net-01
    PING tomcat-net-01 (192.168.0.2) 56(84) bytes of data.
    64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.092 ms
    #反向也是可以ping通的
    [root@zhourui /]# docker exec -it tomcat-net-01 ping tomcat01
    PING tomcat01 (192.168.0.4) 56(84) bytes of data.
    64 bytes from tomcat01.mynet (192.168.0.4): icmp_seq=1 ttl=64 time=0.118 ms
    #tomcat02 是没有连接上 mynet 的
    [root@zhourui /]# docker exec -it tomcat02 ping tomcat-net-01
    ping: tomcat-net-01: Name or service not known
    
    

    结论:如果需要跨网络操作,就需要使用 docker network connect 网络 容器名称 来联通!!

    部署Redis集群

    #创建redis的网络
    docker network create redis --subnet 172.38.0.0/16
    
    #通过脚本创建6个redis配置
    for port in $(seq 1 6); 
    do 
    mkdir -p /mydata/redis/node-${port}/conf
    touch /mydata/redis/node-${port}/conf/redis.conf
    cat << EOF >/mydata/redis/node-${port}/conf/redis.conf
    port 6379
    bind 0.0.0.0
    cluster-enabled yes
    cluster-config-file nodes.conf
    cluster-node-timeout 5000
    cluster-announce-ip 172.38.0.1${port}
    cluster-announce-port 6379
    cluster-announce-bus-port 16379
    appendonly yes
    EOF
    done
    
    docker run -p 637${port}:6379 -p 1637${port}:16379 --name redis-${port} 
    -v /mydata/redis/node-${port}/data:/data 
    -v /mydata/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf 
    -d --net redis --ip 172.38.0.1${port} redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf; 
    
    #=====================================================================
    #单个启动
    docker run -p 6371:6379 -p 16371:16379 --name redis-1 
    -v /mydata/redis/node-1/data:/data 
    -v /mydata/redis/node-1/conf/redis.conf:/etc/redis/redis.conf 
    -d --net redis --ip 172.38.0.11 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
    
    docker run -p 6372:6379 -p 16372:16379 --name redis-2 
    -v /mydata/redis/node-2/data:/data 
    -v /mydata/redis/node-2/conf/redis.conf:/etc/redis/redis.conf 
    -d --net redis --ip 172.38.0.12 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
    
    docker run -p 6373:6379 -p 16373:16379 --name redis-3 
    -v /mydata/redis/node-3/data:/data 
    -v /mydata/redis/node-3/conf/redis.conf:/etc/redis/redis.conf 
    -d --net redis --ip 172.38.0.13 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
    
    #创建集群
    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
    
    [root@zhourui /]# docker exec -it redis-1 /bin/sh
    /data # redis-cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:6379 172.38.0.15:6379 172.38.0.16:6379 --cluster-replicas 1
    >>> Performing hash slots allocation on 6 nodes...
    Master[0] -> Slots 0 - 5460
    Master[1] -> Slots 5461 - 10922
    Master[2] -> Slots 10923 - 16383
    Adding replica 172.38.0.15:6379 to 172.38.0.11:6379
    Adding replica 172.38.0.16:6379 to 172.38.0.12:6379
    Adding replica 172.38.0.14:6379 to 172.38.0.13:6379
    M: 1524f57c751c662847b24edb3cf4433e42e11dae 172.38.0.11:6379
       slots:[0-5460] (5461 slots) master
    M: 3d0a68b584e5935b6174d8b8e0603a14eb246393 172.38.0.12:6379
       slots:[5461-10922] (5462 slots) master
    M: cce404917b84b790cf39ac1f6dff85c1c080c9a1 172.38.0.13:6379
       slots:[10923-16383] (5461 slots) master
    S: 2fb9e53fde60fb288e87a8bccf37f2d521c5f5be 172.38.0.14:6379
       replicates cce404917b84b790cf39ac1f6dff85c1c080c9a1
    S: d977bb4c2b2a45bbbeb74cc123bd87dba1acd257 172.38.0.15:6379
       replicates 1524f57c751c662847b24edb3cf4433e42e11dae
    S: 317ccf18aefe00a7a45820b6509bd8c9fc1f7097 172.38.0.16:6379
       replicates 3d0a68b584e5935b6174d8b8e0603a14eb246393
    Can I set the above configuration? (type 'yes' to accept): yes
    >>> Nodes configuration updated
    >>> Assign a different config epoch to each node
    >>> Sending CLUSTER MEET messages to join the cluster
    Waiting for the cluster to join
    ..
    >>> Performing Cluster Check (using node 172.38.0.11:6379)
    M: 1524f57c751c662847b24edb3cf4433e42e11dae 172.38.0.11:6379
       slots:[0-5460] (5461 slots) master
       1 additional replica(s)
    M: cce404917b84b790cf39ac1f6dff85c1c080c9a1 172.38.0.13:6379
       slots:[10923-16383] (5461 slots) master
       1 additional replica(s)
    M: 3d0a68b584e5935b6174d8b8e0603a14eb246393 172.38.0.12:6379
       slots:[5461-10922] (5462 slots) master
       1 additional replica(s)
    S: 317ccf18aefe00a7a45820b6509bd8c9fc1f7097 172.38.0.16:6379
       slots: (0 slots) slave
       replicates 3d0a68b584e5935b6174d8b8e0603a14eb246393
    S: d977bb4c2b2a45bbbeb74cc123bd87dba1acd257 172.38.0.15:6379
       slots: (0 slots) slave
       replicates 1524f57c751c662847b24edb3cf4433e42e11dae
    S: 2fb9e53fde60fb288e87a8bccf37f2d521c5f5be 172.38.0.14:6379
       slots: (0 slots) slave
       replicates cce404917b84b790cf39ac1f6dff85c1c080c9a1
    [OK] All nodes agree about slots configuration.
    >>> Check for open slots...
    >>> Check slots coverage...
    [OK] All 16384 slots covered.
    
    
    /data # redis-cli -c
    127.0.0.1:6379> cluster info
    127.0.0.1:6379> cluster nodes
    127.0.0.1:6379> set a b
    -> Redirected to slot [15495] located at 172.38.0.13:6379
    OK
    172.38.0.13:6379> 
    
    #新建窗口  docker stop redis-3
    #获取 a 的值
    127.0.0.1:6379> get a
    -> Redirected to slot [15495] located at 172.38.0.14:6379
    "b"
    
    

    搭建redis集群完成!!

    SpringBoot打包Dockers镜像

    1. 构建一个SpringBoot项目

      @RestController
      public class HelloController {
          @RequestMapping("/hello")
          public String hello(){
      
              return "Hello zhour!";
          }
      }
      
    2. 打包应用,package

    3. 编写dockerfile

      FROM java:8
      
      COPY *.jar /app.jar
      
      CMD ["---server port 8080---"]
      
      EXPOSE 8080
      
      ENTRYPOINT ["java","-jar","app.jar"]
      
    4. 构建镜像(使用 ftp 将文件上传至服务器)

      [root@zhourui idea]# ls
      demo-docker-0.0.1-SNAPSHOT.jar  Dockerfile
      [root@zhourui idea]# docker build -t boottestzr .
      
      
    5. 发布运行

      [root@zhourui idea]# docker run -d -P --name ideaboot-web boottestzr
      
    6. 访问

    如需浏览器访问,阿里云开发端口,或者运行时 -p 暴漏已开放的端口即可!!

  • 相关阅读:
    Jquery 复习01
    工具和资源
    常用 npm 和 yarn 命令
    Jenkins 安装 ruby-runtime 出错
    shiro+jwt 实现权限控制
    Sql Server 2008 R2 查询一个实例中存在某个表的数据库
    使用sqlcmd执行连接的时候一直报有语法错误
    Linux信号
    记一次内存爆涨分析 , JVM命令使用
    Java,List操作技巧
  • 原文地址:https://www.cnblogs.com/zhou-zr/p/14698345.html
Copyright © 2011-2022 走看看