【狂神说Java】Docker最新超详细版教程通俗易懂 - 学习笔记

传送门:官方参考文档 | Docker Hub镜像仓库 | 【狂神说Java】Docker视频教程

Docker概述

Docker 是一个便携的应用容器,基于 Go 语言开发的。它可以让开发者打包应用以及应用的依赖到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上。容器是完全使用沙箱机制,相互之间不会有任何接口,非常适合于高密度环境以及中小型部署,而且可以用更少的资源做更多的事情。
Docker 从 17.03 版本之后分为 CE(Community Edition: 社区版) 和 EE(Enterprise Edition: 企业版),我们用社区版就可以了。

Docker可以干什么?

Docker 提供了一个基础系统镜像作为运行应用的基础。Docker 并不在乎你的应用程序是什么、做什么,也就是说,只要是 Linux 系统上的应用都可以运行在 Docker 容器中。这是因为 Docker 提供了一组应用打包、传输和部署的方法,以便你能更好地在容器内运行任何应用。
例如:Docker 只需要一条命令便可以运行 MySQL 数据库:

[root@localhost ~]# docker run -d -p 3306:3306 tutum/mysql

比较Docker和虚拟机的不同

  1. 传统虚拟机,虚拟出硬件,运行一个完整的操作系统,然后在这个系统上安装和运行软件。
  2. Docker利用 Linux 原生支持的容器方式实现资源和环境的隔离,直接利用宿主内核,性能接近原生。
  3. 每个容器都是相互隔离的,每个容器都有属于自己的文件系统,互不影响。
    Docker和虚拟机的不同结构

Docker容器化带来的好处

DevOps思想:它涵盖开发、测试、运维的整个过程,其核心就是流程的统一和自动化。

  1. 系统应用可以更快速的交付和部署
    传统方式:部署前需要写一堆的文档,安装程序;使用Docker:打包镜像发布,一键运行
  2. 更便捷的升级和扩容
    使用Docker后,我们部署系统应用就像搭积木一样。项目打包为一个镜像,在服务器A部署后,一键扩容到服务器B!
  3. 更简单的系统运维
    在容器化以后,我们的开发、测试环境可以做到高度一致。
  4. 更高效的计算资源利用
    Docker 是内核级别的虚拟化,可以在一个物理机上运行很多的容器实例,服务器的性能可以被压榨到极致。

Docker的基本组成部分

镜像(Image): Docker镜像就好比是一个模板,可以通过这个模板来创建容器服务。一个镜像可以创建多个容器。比如,Tomcat镜像 ===> Run ===> Tomcat容器(可以提供服务)

容器(Containers): Docker利用容器技术,可以独立运行一个或一组应用,它是通过镜像来创建的。我们可以把容器理解为就是一个微型的Linux系统。它包括启动、停止、删除等基本命令。

仓库(Repository): 就是存放镜像的地方,一个Docker Registry中可以包含多个仓库(Repository);每个仓库可以包含多个标签(Tag);每个标签对应一个镜像。官方默认的Registry是 Docker Hub,在国内使用时一般需要配置镜像加速。

Docker的基本组成部分

安装Docker环境

注意:在CentOS系统上安装Docker引擎时,要求操作系统是CentOS 7以上版本。可以通过如下命令查看系统内核与系统版本。

# 系统内核版本
[root@localhost ~]# uname -r 
# 查看系统版本
[root@localhost ~]# cat /etc/os-release 
  1. 卸载旧版本
    如果安装了这些,请卸载它们以及相关的依赖项

    [root@localhost ~]# yum remove docker \
                      docker-client \
                      docker-client-latest \
                      docker-common \
                      docker-latest \
                      docker-latest-logrotate \
                      docker-logrotate \
                      docker-engine
    
  2. 添加Docker的yum源信息

    # 安装 yum-utils
    [root@localhost ~]# yum install -y yum-utils
    # (推荐)使用阿里云的软件源地址
    [root@localhost ~]# yum-config-manager \
        --add-repo \
        https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
    # (不推荐)国外地址
    [root@localhost ~]# yum-config-manager \
        --add-repo \
        https://download.docker.com/linux/centos/docker-ce.repo
    

    小贴士: yum-utils 提供了 yum-config-manager 的实用程序

  3. 安装前建议更新 yum 软件包索引

    [root@localhost ~]# yum makecache fast
    

    小贴士:该操作的目的就是将软件包信息提前在本地缓存一份,用来提高搜索安装软件的速度。如果觉得 yum 下载的软件包占用磁盘空间,可以使用 yum clean [all / 软件包] 指令清除缓存。

  4. 安装docker相关的配置

    [root@localhost ~]# yum install docker-ce docker-ce-cli containerd.io
    

    小贴士:docker-ce 是社区版,docker-ee 企业版

  5. 启动 Docker 并设置开机启动

    # 启动 Docker
    [root@localhost ~]# systemctl start docker 
    # 查看当前版本号,是否启动成功 
    [root@localhost ~]# docker version 
    # 设置开机自启动 
    [root@localhost ~]# systemctl enable docker
    
  6. 运行 hello-world 看看效果

    # 运行hello-world
    [root@localhost ~]# docker run hello-world
    # 查看下载的 hello-world 镜像
    [root@localhost ~]# docker images
    
  7. Docker卸载

    # 1. 卸载依赖 
    [root@localhost ~]# yum remove docker-ce docker-ce-cli containerd.io 
    # 2. 删除资源  /var/lib/docker 是 Docker 的默认工作路径
    [root@localhost ~]# rm -rf /var/lib/docker
    

    小贴士:Docker官方的安装文档也比较详细,有需要的小伙伴可以查阅 官方安装文档(CentOS)

Docker 配置阿里云镜像加速

使用加速器可以提升获取Docker官方镜像的速度,在不同的操作系统下,配置加速器的方式略有不同,下文将介绍主要操作系统的配置方法。

  1. 获取加速器的地址
    您登录容器镜像服务控制台后,在左侧导航栏选择镜像工具 > 镜像加速器,在镜像加速器页面就会显示为您独立分配的加速器地址。

    例如:
    加速器地址:[系统分配前缀].mirror.aliyuncs.com
    
  2. 配置加速器
    当您安装的Docker Version不低于1.10时,建议直接通过daemon config进行配置。使用配置文件 /etc/docker/daemon.json (没有时新建该文件)。

    {
         "registry-mirrors": ["<your accelerate address>"]
    }    
    
  3. 重启Docker Daemon即可

    [root@localhost ~]# sudo systemctl daemon-reload 
    [root@localhost ~]# sudo systemctl restart docker
    

    小贴士:阿里云官方也提供了更加详细的说明文档,有需要的小伙伴可以查阅 阿里云官方帮助文档

Docker常用命令汇总

Docker是一个 Client - Server 结构的系统,因此它提供了在客户端 - 服务器环境中进行交互和工作的命令。在这里,我们列出了一些重要和常用的 Docker 命令进行学习。

基础命令

  1. 查看Docker的版本信息

    [root@localhost ~]# docker version
    
  2. 查看Docker的系统信息,包括镜像和容器的数量

    [root@localhost ~]# docker info
    
  3. 帮助命令(可查看可选的参数)

    [root@localhost ~]# docker 命令 --help
    

镜像命令

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

    [root@localhost ~]# docker images
    REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
    hello-world   latest    feb5d9fea6a5   2 months ago   13.3kB
    
    # 可选参数
    -a,--all       # 列出所有镜像
    -q,--quiet     # 只显示镜像的id
    
  2. docker search 搜索镜像
    搜索镜像时建议优先使用 官网镜像仓库 ,那里有完善的文档信息。

    [root@localhost ~]# docker search mysql          
    NAME                              DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
    mysql                             MySQL is a widely used, open-source relation…   11833     [OK]       
    mariadb                           MariaDB Server is a high performing open sou…   4505      [OK]       
    mysql/mysql-server                Optimized MySQL Server Docker images. Create…   887                  [OK]
    centos/mysql-57-centos7           MySQL 5.7 SQL database server                   92                   
    mysql/mysql-cluster               Experimental MySQL Cluster Docker images. Cr…   90                   
    
    # 可选参数
      -f, --filter filter   # 根据所提供的条件过滤输出 如:docker search mysql --filter STARS=5000
          --format string   # 输出打印模板,如:docker search --format "{{.Name}}: {{.StarCount}}" nginx
          --limit int       # 最大搜索结果数(默认为25)
          --no-trunc        # 不截断输出
    
  3. docker pull 镜像名[:tag] 下载镜像

    [root@localhost ~]# docker pull mysql
    Using default tag: latest            # 如果下载命令中部指定tag,则默认下载latest
    latest: Pulling from library/mysql
    ffbb094f4f9e: Pull complete          # 分层下载,docker image的核心-联合文件系统
    df186527fc46: Pull complete 
    fa362a6aa7bd: Pull complete 
    5af7cb1a200e: Pull complete 
    949da226cc6d: Pull complete 
    bce007079ee9: Pull complete 
    eab9f076e5a3: Pull complete 
    8a57a7529e8d: Pull complete 
    b1ccc6ed6fc7: Pull complete 
    b4af75e64169: Pull complete 
    3aed6a9cd681: Pull complete 
    23390142f76f: Pull complete 
    Digest: sha256:ff9a288d1ecf4397967989b5d1ec269f7d9042a46fc8bc2c3ae35458c1a26727
    Status: Downloaded newer image for mysql:latest
    docker.io/library/mysql:latest         # 下载来源的真实地址  
    
    # 如下两个命令是等价的
    [root@localhost ~]# docker pull mysql
    [root@localhost ~]# docker pull docker.io/library/mysql:latest
    # 下载指定版本试一试
    [root@localhost ~]# docker pull mysql:5.7
    
  4. docker rmi 删除镜像

    # 删除指定的镜像
    [root@localhost ~]# docker rmi -f 镜像id
    # 删除多个镜像
    [root@localhost ~]# docker rmi -f  镜像id 镜像id 镜像id
    # 删除全部的镜像
    [root@localhost ~]# docker rmi -f  $(docker images -aq)
    
    # 可选参数
      -f, --force      # 强制移除
          --no-prune   # 不移除该镜像的过程镜像,默认移除
    

容器命令

  1. 如拉取一个 centos 镜像

    [root@localhost ~]# docker pull centos
    
  2. 运行容器并进入容器

    [root@localhost ~]# docker run --name CentOS -it centos /bin/bash
    [root@d6cbf0e93a8b /]# ls   # 进入到centos容器中,展示根目录下的文件
    bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
    
    # 重要参数说明
    --name string          # 指定容器名字
    -d                     # 后台方式运行
    -it                    # 使用交互方式运行,进入容器查看内容
    -p                     # 指定容器的端口及主机端口映射,三种示例如下
        -p ip:主机端口:容器端口 
        -p 主机端口:容器端口    # 推荐
        -p 容器端口
    -P                      # 随机指定端口(大写的P)
    

    小贴士: docker run -it centos /bin/bash 命令后面的 bin/bash 的作用,表示载入容器后运行bash ,Docker中必须要保持一个进程的运行,要不然整个容器启动后就会马上停止,这个 /bin/bash 就表示启动容器后启动 bash。

  3. 后台方式运行容器

    # 后台方式运行 centos 容器,因为没有前台进程使用,会马上停止运行
    [root@localhost ~]# docker run --name CentOS_01 -d centos
    ecbc3e9d773d120ba0cc14ba064cc9eeb843cd23bab81b1fb9724f045319874d
    [root@localhost ~]# docker ps -n 1   
    CONTAINER ID   IMAGE     COMMAND       CREATED              STATUS                          PORTS     NAMES
    ecbc3e9d773d   centos    "/bin/bash"   About a minute ago   Exited (0) About a minute ago             CentOS_01
    
    # 运行一个脚本,使得 centos 容器保持运行状态
    [root@localhost ~]# docker run --name CentOS_02 -d centos /bin/sh -c "while true;do echo hi;sleep 5;done"
    [root@localhost ~]# docker ps -n 1
    CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS     NAMES
    67a894effbcf   centos    "/bin/sh -c 'while t…"   4 seconds ago   Up 3 seconds             CentOS_02
    
    # 查看容器的日志信息
    [root@localhost ~]# docker logs -tf --tail 3  67a894effbcf  
    2021-12-17T15:03:36.016984749Z hi
    2021-12-17T15:03:41.030581591Z hi
    2021-12-17T15:03:46.037004793Z hi
    2021-12-17T15:03:51.045708743Z hi
    

    小贴士:Docker容器后台运行时,必须要有一个前台的进程,否则会自动停止。

  4. 退出容器

    # exit 停止并退出容器(以后台方式运行时,则仅退出容器)
    # Ctrl+P+Q  不停止容器退出
    
    [root@d6cbf0e93a8b /]# exit
    exit
    [root@localhost ~]#
    
  5. 列出系统中的容器

    [root@localhost ~]# docker ps
    CONTAINER ID   IMAGE     COMMAND       CREATED          STATUS          PORTS     NAMES
    d6cbf0e93a8b   centos    "/bin/bash"   30 seconds ago   Up 28 seconds             CentOS
    [root@localhost ~]# docker ps -a
    CONTAINER ID   IMAGE          COMMAND       CREATED          STATUS                   PORTS     NAMES
    d6cbf0e93a8b   centos         "/bin/bash"   34 seconds ago   Up 32 seconds                      CentOS
    54f01f55548d   feb5d9fea6a5   "/hello"      7 hours ago      Exited (0) 7 hours ago             friendly_chandrasekhar
    
    # 可选参数,不带参数默认列出当前正在运行的容器
    -a           # 列出所有容器的运行记录 
    -n=?         # 显示最近创建的n个容器 
    -q           # 只显示容器的编号
    
  6. 删除容器

    [root@localhost ~]# docker rm 容器id                 # 删除指定的容器,不能删除正在运行的容器,强制删除使用 rm -f
    [root@localhost ~]# docker rm -f $(docker ps -aq)    # 删除所有的容器
    [root@localhost ~]# docker ps -a -q|xargs docker rm  # 删除所有的容器
    
  7. 启动和停止容器

    [root@localhost ~]# docker start 容器id          # 启动容器
    [root@localhost ~]# docker restart 容器id        # 重启容器
    [root@localhost ~]# docker stop 容器id           # 停止当前运行的容器
    [root@localhost ~]# docker kill 容器id           # 强制停止当前容器
    

其他常用命令

  1. 日志的查看

    [root@localhost ~]# docker logs -tf 容器id 
    [root@localhost ~]# docker logs --tail number 容器id         # 注意:number为要显示的日志条数
    
  2. 查看容器中进程信息

    [root@localhost ~]# docker top d6cbf0e93a8b
    UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
    root                3825                3806                0                   22:43               pts/0               00:00:00            /bin/bash
    
  3. 查看容器的元数据

    [root@localhost ~]# docker inspect d6cbf0e93a8b
    
  4. 进入当前正在运行的容器
    因为通常我们的容器都是使用后台方式来运行的,有时需要进入容器修改配置信息
    方式一(推荐): docker exec 进入容器后开启一个新的终端,可以在里面操作,使用 exit 退出时,不会停止容器运行

    [root@localhost ~]# docker exec -it d6cbf0e93a8b /bin/bash
    [root@d6cbf0e93a8b /]# ls
    bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
    [root@d6cbf0e93a8b /]# ps -ef
    UID         PID   PPID  C STIME TTY          TIME CMD
    root          1      0  0 14:43 pts/0    00:00:00 /bin/bash
    root         23      0  0 15:12 pts/1    00:00:00 /bin/bash
    root         38     23  0 15:12 pts/1    00:00:00 ps -ef
    [root@d6cbf0e93a8b /]# exit
    exit
    [root@localhost ~]# docker ps
    CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS     NAMES
    d6cbf0e93a8b   centos    "/bin/bash"              31 minutes ago   Up 31 minutes             CentOS
    

    方式二(不推荐): docker attach 进入容器正在执行的终端,不会启动新的进程,使用 exit 退出时,会停止容器运行

    [root@localhost ~]# docker attach d6cbf0e93a8b
    [root@d6cbf0e93a8b /]# exit
    exit
    [root@localhost ~]# docker ps
    CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS     NAMES
    
  5. 拷贝操作

    # 拷贝容器的文件到主机中
    docker cp 容器id:容器内路径  目的主机路径
    # 拷贝宿主机的文件到容器中
    docker cp 目的主机路径 容器id:容器内路径
    

操作命令小结

Docker有很多操作(Docker CLI 的基础命令),我们没必要记住所有命令的具体使用方法。学习方法,我们可以通过命令 docker command --help 更深入的了解指定的 Docker 命令使用方法。例如:我们要查看 docker images 指令的具体使用方法:

[root@localhost ~]# docker images --help

在这里插入图片描述

Docker数据卷技术

为什么需要数据卷?什么是数据卷?

利用前面学习到的技术部署容器,容器运行所需的配置信息和数据文件都是保存在该容器中的。这就会导致容器被删除后,容器中产生的数据也就没有了。那怎么才能做到容器数据的持久化呢?
使用下面介绍的数据卷技术就可以做到容器之间数据的共享和容器与本地之间的持久化存储。

使用数据卷

  • 方式一:直接使用命令参数来挂载
    命令: docker run -it -v 宿主机目录:容器目录
    实战:安装MySQL

    # 安装MySQL数据库,设置密码为123456,并挂载两个数据卷用于存储配置和数据信息
    [root@localhost ~]# docker run --name MySQL -d -p 3306:3306 \
                        -e MYSQL_ROOT_PASSWORD=123456 \
                        -v /home/mysql/conf:/etc/mysql/conf \
                        -v /home/mysql/data:/var/lib/mysql \
                        mysql:5.7
    # 此时可以通过数据库可视化工具连接到MySQL,并尝试创建一下数据表
    # 删除MySQL容器
    [root@localhost ~]# docker rm -f MySQL
    # 执行执行数据库安装后,之前MySQL中的创建的数据表依然存在
    

    执行数据卷挂载以后,我们可以通过 docker inspect 容器名 命令,在元数据信息中查看数据卷情况,结果如下:
    在这里插入图片描述
    当然也可以通过 docker volume inspect 数据卷名 命令,查看数据卷挂载情况。如下:
    在这里插入图片描述

  • 方式二:使用Dockerfile脚本挂载数据卷
    初识 Dockerfile ,使用 Dockerfile 中的 VOLUME 指令来给镜像添加一个或多个数据卷。 Dockerfile 脚本比较简单,按照如下步骤操作即可:

    # 编写 Dockerfile 脚本
    [root@localhost home]# vi dockerfile01
    
    # 脚本内容
    # 每个指令必须是大写字母,一个指令代表一个新的镜像层
    FROM centos                         # FROM:基础镜像,一切基于这个开始构建
    VOLUME ["volume01","volume02"]      # VOLUME:挂载的目录
    CMD echo "----end----"              # CMD:容器启动时要运行的命令
    CMD /bin/bash
    
    # 执行构建镜像
    [root@localhost home]# docker build -f dockerfile01 -t wangxf/centos:1.0 .
    # 查看镜像
    [root@localhost home]# docker images
    REPOSITORY            TAG       IMAGE ID       CREATED          SIZE
    wangxf/centos         1.0       af2f08491630   22 seconds ago   231MB
    # 启动自己生成的容器
    [root@localhost home]# docker run -it af2f08491630 /bin/bash
    [root@c60faa5b4dea /]# ls v
    var/      volume01/ volume02/ 
    
    # 解析:上面的volume01  volume02两个目录就是刚刚通过Dockerfile挂载的数据卷,自己动手找一下他们分别挂载到宿主机的什么位置呢?
    

匿名挂载和具名挂载

  • 匿名挂载

    # 匿名挂载:-v 容器内路径
    [root@localhost data]# docker run -d -p 80:80 --name Nginx -v /ect/nginx nginx
    
  • 具名挂载

    # 具名挂载:-v 卷名:容器内路径
    [root@localhost data]# docker run -d -p 80:80 --name Nginx_JM -v juming-nginx:/ect/nginx nginx
    # 查看卷情况
    [root@localhost data]# docker volume ls    
    DRIVER    VOLUME NAME
    local     40104546065ec402615d03842c6b7d6cbdb8e43413666c697ea4980baaa36477
    local     cd637459e5acab02e1935d098a916d873727f0f83d0377dc7caf17be5c170fb0
    local     juming-nginx
    # 查看具名卷在配置路径
    [root@localhost data]# docker volume inspect juming-nginx
    [
        {
            "CreatedAt": "2021-12-18T18:45:24+08:00",
            "Driver": "local",
            "Labels": null,
            "Mountpoint": "/var/lib/docker/volumes/juming-nginx/_data",
            "Name": "juming-nginx",
            "Options": null,
            "Scope": "local"
        }
    ]
    

    小贴士:所有的Docker容器内的卷,在没有指定目录的情况下都是在 /var/lib/docker/volumes/卷名称/_data/ 路径下

只读和可读可写权限

在 -v 可选参数后面追加 :ro / :rw ,可以改变读写权限。
:ro,readonly即只读权限,说明这个路径只能通过宿主机来操作,容器内部是无法操作的
:rw,readwrite即可读可写权限,默认就是它

# 一旦设置了容器权限,容器对我们挂载出来的内容就是限定的了
[root@localhost data]# docker run -d -p 80:80 --name Nginx_JM -v juming-nginx:/ect/nginx:ro nginx
[root@localhost data]# docker run -d -p 80:80 --name Nginx_JM -v juming-nginx:/ect/nginx:rw nginx

多个容器间数据如何同步?

通过容器数据卷就可以实现同步多个容器间的数据。
在这里插入图片描述
实操示例:下面我们在创建两个 centos 容器,并对两个容器建立数据卷共享关系。

  1. 新创建一个 centos_01 容器,并进行指定路径挂载

    [root@localhost ~]# docker run -it --name centos_01 -v /webapp:/webapp centos
    # 此时在 centos_01 容器或者宿主机容器的 /webapp 目录新建文件,两者都会自动同步
    
  2. 通过 --volumes-from 可选参数,与 centos_01 容器建立容器数据卷挂载关系

    [root@localhost ~]# docker run -it --name centos_02 --volumes-from centos_01 centos
    # 创建好 centos_02 容器以后,发现 /webapp 目录中的内容与 centos_01 容器、宿主机容器中的 /webapp 目录的内容相同
    
  3. 删除 centos_01 容器,然后进入 centos_02 看看数据卷中的内容还是否存在

    [root@localhost volumes]# docker rm -f centos_01
    [root@localhost volumes]# docker exec -it centos_02 /bin/bash
    [root@3c9e9153aa30 /]# cd /webapp/ && ls
    wangxf.java
    

数据卷小结

容器之间数据卷的生命周期一直持续到没有容器使用为止。但是如果你的数据卷中的数据持久化到本地后,本地数据是不会删除的。

Dockerfile

什么是Dockerfile?

Dockerfile就是用来构建Docker镜像的脚本文件,实际上就是一个命令脚本。通过这个脚本就可以生成镜像,镜像是一层一层的,那么脚本中的每个命令都是一层。
Dcoker镜像的分层
Dockerfile是面向开发者的,发布项目时需要做成镜像,那么就需要编写 Dockerfile 脚本文件。涉及如下几个关键点:

  1. Dockerfile:构建文件,定义了一切的构建步骤,源代码。—— 开发
  2. DockerImages:通过 Dockerfile 构建生成的镜像,最终发布和运行的产品。—— 部署
  3. Docker容器:就是运行起来的镜像,对外提供服务。—— 运维

Dockerfile的基本语法

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

通过 Dockerfile 构建 Docker 镜像的步骤

  1. 编写一个 Dockerfile 脚本
  2. 使用 docker build 命令构建成一个镜像
  3. 使用 docker run 命令运行镜像
  4. 使用 docker push 发布镜像到镜像仓库(DockerHub、阿里云镜像仓库)

Dockerfile的指令

  • 指令说明

    FROM			# 指定基础镜像,一切都要基于这个开始
    MAINTAINER		# 镜像是谁写的,姓名+邮箱(通用标准)
    RUN				# 镜像构建时需要运行的命令
    ADD				# 将本地文件添加到容器中,tar类型文件会自动解压(网络压缩资源不会被解压),可以访问网络资源
    WORKDIR			# 镜像的工作目录
    VOLUME			# 挂载的目录
    EXPOSE			# 对外暴露的端口
    CMD				# 指定这个容器启动的时候要运行的命令(只有最后一个会生效)
    ENTRYPOINT		# 指定这个容器启动的时候要运行的命令,可以追加命令
    ONBUILD			# 当构建一个被继承DockerFile,这个时候就会运行ONBUILD的指令,触发指令
    COPY			# 功能类似ADD,但是是不会自动解压文件,也不能访问网络资源
    ENV				# 构建的时候设置环境变量 
    
  • 实操练习,实现一个自己的 centos 容器

  1. 首先编写一个 Dockerfile 脚本文件,内容如下:

    [root@localhost dockerfile]# vim mydockerfile-centos
    FROM centos
    MAINTAINER wangxf<912309845@qq.com>
    
    ENV MYPATH /usr/local
    WORKDIR $MYPATH 
    
    RUN yum -y install vim            # 安装vim工具
    RUN yum -y install net-tools      # 安装网络基础包
    
    EXPOSE 80
    
    CMD echo $MYPATH
    CMD echo "--- END ---"
    CMD /bin/bash
    
  2. 通过 Dockerfile 脚本构建镜像文件
    命令: docker build -f dockerfile文件路径 -t 镜像名:[TAG] . ,注意最后的点

    [root@localhost dockerfile]# docker build -f mydockerfile-centos -t mycentos:0.1 .
    [root@localhost dockerfile]# docker images
    REPOSITORY            TAG       IMAGE ID       CREATED          SIZE
    mycentos              0.1       9f12990cd386   20 seconds ago   322MB
    

    修改镜像TAG

    [root@localhost dockerfile]# docker tag 9f12990cd386 mycentos:0.2
    
  3. 测试运行

    # 运行容器
    [root@localhost dockerfile]# docker run -it mycentos:0.1
    # 运行容器后,自动进入到 /usr/local 目录
    [root@6eb7f871b213 local]# pwd
    /usr/local
    # 看看我们安装的网络基础包是否生效了
    [root@6eb7f871b213 local]# ifconfig
    eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        其他内容省略……
    
  4. 查看镜像的变更历史

    [root@localhost dockerfile]# docker history 9f12990cd386
    IMAGE          CREATED          CREATED BY                                      SIZE      COMMENT
    9f12990cd386   14 minutes ago   /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "/bin…   0B        
    7e99c710a5d5   14 minutes ago   /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "echo…   0B        
    ae48ddb633e8   14 minutes ago   /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "echo…   0B        
    7079d2482219   14 minutes ago   /bin/sh -c #(nop)  EXPOSE 80                    0B        
    5e2d68b08b92   14 minutes ago   /bin/sh -c yum -y install net-tools             27MB      
    ecf92b08e7bf   14 minutes ago   /bin/sh -c yum -y install vim                   64.1MB    
    63e10164af59   15 minutes ago   /bin/sh -c #(nop) WORKDIR /usr/local            0B        
    1910d234fba0   15 minutes ago   /bin/sh -c #(nop)  ENV MYPATH=/usr/local        0B        
    a7f48ed49a91   15 minutes ago   /bin/sh -c #(nop)  MAINTAINER wangxf<9123098…   0B        
    5d0da3dc9764   3 months ago     /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B        
    <missing>      3 months ago     /bin/sh -c #(nop)  LABEL org.label-schema.sc…   0B        
    <missing>      3 months ago     /bin/sh -c #(nop) ADD file:805cb5e15fb6e0bb0…   231MB    
    
  • 实操练习,实现一个Tomcat镜像
  1. 准备镜像文件,Tomcat压缩包,JDK压缩包

    # 为了跳过Oracle对其资源的下载限制,JDK下载需要设置请求头信息
    [root@localhost dockerfile]# wget --no-check-certificate -c --header="Cookie: oraclelicense=accept-securebackup-cookie" \
                                    http://download.oracle.com/otn-pub/java/jdk/8u131-b11/d54c1d3a095b4ff2b6607d096fa80163/jdk-8u131-linux-x64.tar.gz
    # Tomcat下载
    [root@localhost dockerfile]# wget https://archive.apache.org/dist/tomcat/tomcat-8/v8.0.23/bin/apache-tomcat-8.0.23.tar.gz
    [root@localhost dockerfile]# ls
    apache-tomcat-8.0.23.tar.gz  jdk-8u131-linux-x64.tar.gz
    
  2. 编写 Dockerfile 脚本文件,文件名建议使用官方命名:Dockerfile ,这样在 docker build 时会默认寻找当前目录下的文件,不需要使用 -f 参数进行指定了。

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

    [root@localhost dockerfile]# docker build -t diytomcat:1.0 .
    
  4. 启动镜像

    [root@localhost dockerfile]# docker run -d -p 9090:8080 --name diytomcat \
        -v /home/dockerfile/tomcat/webapps/test:/usr/local/apache-tomcat-8.0.23/webapps/test \
        -v /home/dockerfile/tomcat/logs:/usr/local/apache-tomcat-8.0.23/logs \
        diytomcat:1.0
    
  5. 测试访问:http://your_ip:9090/

  6. 发布项目,我们在本地挂载的数据卷中进行项目发布,发布后访问http://your_ip:9090/test

    [root@localhost dockerfile]# cd /home/dockerfile/tomcat/webapps/test
    [root@localhost test]# cat index.jsp 
    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>Hello World</title>
    </head>
    <body>
    Hello World!<br/>
    <% out.println("你的 IP 地址 " + request.getRemoteAddr()); %>
    </body>
    </html>
    

发布自己的镜像

参考官方文档:容器镜像服务

Dockerfile小结

在这里插入图片描述

Docker网络原理

Docker的网络模式

安装Docker的时候,它会自动创建四个网络:bridge(创建容器默认连接到此网络),host,container,none。在Docker 1.9版本以后新增了用户自定义网络模式

  • bridge模式(即 --net=bridge),这是Dokcer网络的默认设置,为容器创建独立的网络命名空间,容器具有独立的网卡等所有单独的网络栈,是最常用的使用方式。 在 docker run 启动容器的时候,如果不加 --net 参数,就默认采用这种网络模式。安装完 Docker,系统会自动添加一个供 Docker 使用的网桥 docker0,我们创建一个新的容器时, 容器通过 DHCP 获取一个与 docker0 同网段的IP地址,并默认连接到 docker0 网桥,以此实现容器与宿主机的网络互通。
  • host模式(即 --net=host), 这个模式下创建出来的容器,直接使用容器宿主机的网络命名空间。 将不拥有自己独立的 Network Namespace,即没有独立的网络环境。它使用宿主机的ip和端口。
  • container模式(即 --net=container:name OR id), 与host模式类似,只是容器将与指定的容器共享网络命名空间。 这个模式就是指定一个已有的容器,共享该容器的IP和端口。除了网络方面两个容器共享,其他的如文件系统,进程等还是隔离开的。
  • none模式(即 --net=none), 为容器创建独立网络命名空间,但不为它做任何网络配置,容器中只有lo,用户可以在此基础上,对容器网络做任意定制。 这个模式下,Dokcer不为容器进行任何网络配置。需要我们自己为容器添加网卡,配置IP。
  • 自定义模式:允许容器使用第三方的网络实现或者创建单独的 bridge 网络,提供网络隔离能力。

理解Docker网络(docker0)

安装 Docker 以后,宿主机会自动配置一个虚拟的网桥叫 docker0,并且 Docker 会在私有 IP 网段中,选择一个和宿主机不同的IP地址和子网分配给 docker0,例如将 172.17.0.1/16 分配给 docker0 网桥 。
一般情况下,使用 Docker 创建一个容器的时候,都会自动创建一对虚拟的网络接口(叫做veth-pair),分别放在宿主机和新容器中,这就是连接各种虚拟网络设备的桥梁。宿主机一端的虚拟接口(即veth)会连接到 docker0 网桥上;而容器一端的虚拟接口(即eth0)只能在该容器内可见,并且会从网桥可用地址段中获取一个空闲地址分配给该容器(例如172.17.0.2/16)。通过这种方式,宿主机可以跟容器通信,容器之间也可以相互通信。Docker 就创建了在宿主机和所有容器之间一个虚拟共享网络。当然用户也可以通过 docker network 命令来手动管理网络。
在这里插入图片描述

docker0 可以通过宿主机的 ip addr 命令进行查看:
在这里插入图片描述
Docker中的网络接口默认都是虚拟的接口。虚拟接口的最大优势就是转发效率极高。这是因为Linux在内核中通过数据复制实现虚拟接口之间的数据转发,即发送接口的发送缓存中的数据包将被直接复制到接收接口的接收缓存中,而无需通过外部物理网络设备进行交换。需要注意的是,当我们删除一个容器后,该容器对应的虚拟网络接口也会随之删除。

容器互联

在微服务部署的场景下,注册中心是使用服务名来唯一识别微服务的,而我们上线部署的时候微服务对应的IP地址可能会改动,所以我们需要使用容器名来配置容器间的网络连接。使用 --link 可以实现这个功能。

  • –link
    使用 --link 实现容器互联

    # 启动 tomcat01
    [root@localhost ~]# docker run -d -P --name tomcat01 tomcat:8.0.20
    # 启动 tomcat02,通过 --link 连接到 tomcat01
    [root@localhost ~]# docker run -d -P --name tomcat02 --link tomcat01 tomcat:8.0.20
    # 进入tomcat02,ping tomcat01
    [root@localhost ~]# docker exec -it tomcat02 ping tomcat01
    PING tomcat01 (172.17.0.1) 56(84) bytes of data.
    64 bytes from tomcat01 (172.17.0.1) : icmp_seq=1 ttl=64 time=0.037 ms
    64 bytes from tomcat01 (172.17.0.1) : icmp_seq=2 ttl=64 time=0.037 ms
    64 bytes from tomcat01 (172.17.0.1) : icmp_seq=3 ttl=64 time=0.039 ms
    

    –link 的网络原理
    其网络通信原理是在容器中配置 host,即在指定容器的 /etc/hosts 文件中添加容器名和 IP 地址映射。所以通过 --link 建立的网络连接是单向的,若容器 A 与容器 B 建立了一条网络连接,只能从 A 向 B 通信,反之则不可。
    目前 --link 设置容器互连的方式已经不推荐使用。更多地选择自定义网络。

  • 自定义网络
    我们可以通过 docker network create <Option> <NetworkName> 命令来创建一个自定义网络。命令说明:

    docker network create <Option> <NetworkName>
    # 可选参数
    --config-from 复制其他网络配置
    --driver 指定网络模式
    --gateway 指定网关,所有的请求都要经过它
    --internal 限制只能内部访问
    --ip-range 从子网范围分配容器IP
    --ipv6 启用IPv6网络
    --subnet 指定网段
    
  1. 创建一个自定义网络

    # 创建一个名叫 mynet 的网络,它的网络模式是 桥接(bridge),网段是 192.168.0.0/16,网关是 192.168.0.1
    [root@localhost ~]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
    # 网络列表
    [root@localhost ~]# docker network ls
    NETWORK ID     NAME      DRIVER    SCOPE
    51604e1eac75   bridge    bridge    local
    9182708c0a34   host      host      local
    2c61a06248d3   mynet     bridge    local
    895dbec7357c   none      null      local
    
  2. 查看自定义的网络信息

    [root@localhost ~]# docker network inspect mynet
    

    网络创建好以后,我们就可以把创建的服务放到自己创建的网络当中。

  3. 使用自定义网络
    现在我们就可以启动容器,并让他们使用自定义网络了。如下,我启动两个Tomcat容器。

    [root@localhost ~]# docker run -it --name tomcat-net-01 --net mynet tomcat:8.0.20 
    [root@localhost ~]# docker run -it --name tomcat-net-01 --net mynet tomcat:8.0.20 
    

    此时,再看看我们的自定义网络,会发现网络中多了两个容器信息。
    在这里插入图片描述
    现在我们在 tomcat-net-01 中直接 ping tomcat-net-02 就可以直接连通。

  4. 自定义网络的好处
    ✓ 自定义网络默认支持 ping 容器名
    ✓ 可以使不同的集群使用不同的网络,保证集群是安全健康的

  • 网络连通
    完成自定义网络后,我们如何实现不同网络间的容器网络连接呢?也就是说,在两个不同的网络间实现网络互通,即 docker0 和 mynet自定义网络 建立网络连接。
    在这里插入图片描述
    这时我们可以通过 docker network connect [Options] NetworkName ContainerName 命令打通不同网络之间的容器连接。

    # 建立网络连接
    [root@localhost ~]# docker network connect mynet tomcat01
    # 查看网络信息
    [root@localhost ~]# docker network inspect mynet
    # 验证网络是否打通了
    [root@localhost ~]# docker exec -it tomcat01 ping tomcat-net-01
    PING centos-net-01 (192.168.0.3): 56 data bytes
    64 bytes from 192.168.0.3: icmp_seq=0 ttl=64 time=0.086 ms
    64 bytes from 192.168.0.3: icmp_seq=1 ttl=64 time=0.205 ms
    64 bytes from 192.168.0.3: icmp_seq=2 ttl=64 time=0.242 ms
    64 bytes from 192.168.0.3: icmp_seq=3 ttl=64 time=0.086 ms
    # 但是此时 tomcat02 是连不通的,因为 tomcat02 与 mynet 还没有建立网络连接
    [root@localhost ~]# docker exec -it tomcat02 ping centos-net-01 
    ping: unknown host
    

    结论:假设要跨网络操作别人,首先需要使用 docker network connect 来实现网络连通!

Docker Compose

Docker Compose是什么?

Docker Compose 是对 Docker 容器进行编排的工具,定义和运行多容器的应用,可以一条命令启动多个容器。
使用三部曲:

  1. Dockerfile 定义应用的运行环境
  2. docker-compose.yml 定义组成应用的各服务,服务编排
  3. docker-compose up 启动整个应用

安装 Docker Compose

# 下载 docker-compose,你可以通过修改URL中的版本,可以自定义您的需要的版本
[root@localhost ~]# curl -L https://get.daocloud.io/docker/compose/releases/download/1.25.5/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose 
# 修改可执行权限
[root@localhost ~]# chmod +x /usr/local/bin/docker-compose
# 查看版本,安装成功
[root@localhost bin]# docker-compose -version 
docker-compose version 1.25.5, build 8a1c60f6

Docker Compose 常用命令

# 默认使用docker-compose.yml构建镜像
[root@localhost ~]# docker-compose build
[root@localhost ~]# docker-compose build --no-cache
# 指定不同yml文件模板用于构建镜像
[root@localhost ~]# docker-compose build -f docker-compose-1.yml

# 列出Compose文件构建的镜像
[root@localhost ~]# docker-compose images                          

# 启动所有编排容器服务,该命令十分强大,它将尝试自动完成包括构建镜像,(重新)创建服务,启动服务,并关联服务相关容器的一系列操作。
[root@localhost ~]# docker-compose up -d

# 查看正在运行中的容器
[root@localhost ~]# docker-compose ps 
# 查看所有编排容器,包括已停止的容器
[root@localhost ~]# docker-compose ps -a
# 停止 up 命令所启动的容器,并移除网络
[root@localhost ~]# docker-compose down

# 进入指定容器执行命令
[root@localhost ~]# docker-compose exec nginx bash 
[root@localhost ~]# docker-compose exec web python manage.py migrate --noinput

# 查看web容器的实时日志
[root@localhost ~]# docker-compose logs -f web
 
# 启动已经存在的服务容器
[root@localhost ~]# docker-compose start
# 停止已经处于运行状态的容器,但不删除它,可以再次重启
[root@localhost ~]# docker-compose stop
# 重新启动停止服务的容器
[root@localhost ~]# docker-compose restart web

# 暂停web容器
[root@localhost ~]# docker-compose pause web
# 恢复web容器
[root@localhost ~]# docker-compose unpause web

# 删除web容器,删除前必需停止stop web容器服务
[root@localhost ~]# docker-compose rm web  

# 查看各个服务容器内运行的进程 
[root@localhost ~]# docker-compose top  

Docker Compose 配置编写规则

# 版本号
version: "3"
# 服务
services:
 # 服务名称
  redis:
   # 镜像名: 仓库/标签:版本
    image: redis:alpine
   # 暴露端口信息
    ports:
      - "6379"
   # 添加环境变量.可以使用数组或字典两种形式
   # 任何布尔值:true, false, yes, no 需要用引号括起来,以确保它们不被YAML解析器转换为True或False 
    environment:
  db:
    image: postgres:9.4
    # 定义全局挂载卷
    volumes:
      - db-data:/var/lib/postgresql/data
    networks:
      - backend
    deploy:
      placement:
        constraints: [node.role == manager]

使用 Docker Compose 一键部署WordPress博客

# 创建一个新的项目目录
[root@localhost home]# mkdir wp_compose
# 进入到项目目录
[root@localhost home]# cd wp_compose
# 创建 docker-compose.yml 文件,编排你的服务,主要内容包括WordPress博客和一个单独的MySQL实例卷挂载数据持久化
[root@localhost wp_compose]# vim docker-compose.yml
version: "3.3"
services:
  db:
    image: mysql:5.7
    volumes:
      - db_data:/var/lib/mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: somewordpress
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress
      MYSQL_PASSWORD: wordpress
  wordpress:
    depends_on:
      - db
    image: wordpress:latest
    volumes:
      - wordpress_data:/var/www/html
    ports:
      - "8000:80"
    restart: always
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD: wordpress
      WORDPRESS_DB_NAME: wordpress
volumes:
  db_data: {}
  wordpress_data: {}

# 启动博客项目
[root@localhost home]# docker-compose up -d
# 预览效果
http://your_ip:8000/

在这里插入图片描述
欢迎关注我的个人公众号:小瓦匠学编程,优质好文不错过!扫描二维码或微信搜索 “小瓦匠学编程” 即可关注。

(本文完)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小瓦匠学编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值