Docker学习笔记

  Docker简介

 是什么

   docker理念


   Docker镜像的设计,使得Docker得以打破过去「程序即应用」的观念。透过镜像(images)将作业系统核心除外,运作应用程式所需要的系统环境,由下而上打包,达到应用程式跨平台间的无缝接轨运作。
 解决了运行环境和配置问题软件容器,方便做持续集成并有助于整体发布的容器虚拟化技术。


  能干嘛


    之前的虚拟机技术

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

 

    容器虚拟化技术

Linux 容器(Linux Containers,缩写为 LXC)。
Linux 容器不是模拟一个完整的操作系统,而是对进程进行隔离。有了容器,就可以将软件运行所需的所有资源打包到一个隔离的容器中。容器与虚拟机不同,不需要捆绑一整套操作系统,只需要软件工作所需的库资源和设置。系统因此而变得高效轻量并保证部署在任何环境中的软件都能始终如一地运行。

比较了 Docker 和传统虚拟化方式的不同之处:
*传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程;
*而容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便。
* 每个容器之间互相隔离,每个容器有自己的文件系统 ,容器之间进程不会相互影响,能区分计算资源。


    开发/运维(DevOps)一次构建、随处运行
        更快速的应用交付和部署

传统的应用开发完成后,需要提供一堆安装程序和配置说明文档,安装部署后需根据配置文档进行繁杂的配置才能正常运行。Docker化之后只需要交付少量容器镜像文件,在正式生产环境加载镜像并运行即可,应用安装配置在镜像里已经内置好,大大节省部署配置和测试验证时间。

        更便捷的升级和扩缩容

随着微服务架构和Docker的发展,大量的应用会通过微服务方式架构,应用的开发构建将变成搭乐高积木一样,每个Docker容器将变成一块“积木”,应用的升级将变得非常容易。当现有的容器不足以支撑业务处理时,可通过镜像运行新的容器进行快速扩容,使应用系统的扩容从原先的天级变成分钟级甚至秒级。

        更简单的系统运维

应用容器化运行后,生产环境运行的应用可与开发、测试环境的应用高度一致,容器会将应用程序相关的环境和状态完全封装起来,不会因为底层基础架构和操作系统的不一致性给应用带来影响,产生新的BUG。当出现程序异常时,也可以通过测试环境的相同容器进行快速定位和修复。
      更高效的计算资源利用

Docker是内核级虚拟化,其不像传统的虚拟化技术一样需要额外的Hypervisor支持,所以在一台物理机上可以运行很多个容器实例,可大大提升物理服务器的CPU和内存的利用率。
    官网
      docker官网:http://www.docker.com
      docker中文网站:https://www.docker-cn.com/
    仓库
      Docker Hub官网: https://hub.docker.com/

 Docker安装

  前提说明

CentOS Docker 安装
Docker支持以下的CentOS版本:
CentOS 7 (64-bit)
CentOS 6.5 (64-bit) 或更高的版本
 
前提条件
目前,CentOS 仅发行版本中的内核支持 Docker。
Docker 运行在 CentOS 7 上,要求系统为64位、系统内核版本为 3.10 以上。
Docker 运行在 CentOS-6.5 或更高的版本的 CentOS 上,要求系统为64位、系统内核版本为 2.6.32-431 或者更高版本。
 
查看自己的内核
uname命令用于打印当前系统相关信息(内核版本号、硬件架构、主机名称和操作系统类型等)。

[root@yangdong ~]# uname -r
3.10.0-1062.el7.x86_64


查看已安装的CentOS版本信息(CentOS6.8有,CentOS7无该命令)

[root@yangdong ~]# cat /etc/redhat-release 
CentOS Linux release 7.7.1908 (Core)

 

Docker的基本组成


  镜像(image)

Docker 镜像(Image)就是一个只读的模板。镜像可以用来创建 Docker 容器,一个镜像可以创建很多容器。



  容器(container)

Docker 利用容器(Container)独立运行的一个或一组应用。容器是用镜像创建的运行实例。它可以被启动、开始、停止、删除。每个容器都是相互隔离的、保证安全的平台。可以把容器看做是一个简易版的 Linux 环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。容器的定义和镜像几乎一模一样,也是一堆层的统一视角,唯一区别在于容器的最上面那一层是可读可写的。

  仓库(repository)

仓库(Repository)是集中存放镜像文件的场所。仓库(Repository)和仓库注册服务器(Registry)是有区别的。仓库注册服务器上往往存放着多个仓库,每个仓库中又包含了多个镜像,每个镜像有不同的标签(tag)。仓库分为公开仓库(Public)和私有仓库(Private)两种形式。最大的公开仓库是 Docker Hub(https://hub.docker.com/),存放了数量庞大的镜像供用户下载。国内的公开仓库包括阿里云 、网易云 等

  小总结

需要正确的理解仓储/镜像/容器这几个概念:
 Docker 本身是一个容器运行载体或称之为管理引擎。我们把应用程序和配置依赖打包好形成一个可交付的运行环境,这个打包好的运行环境就似乎 image镜像文件。只有通过这个镜像文件才能生成 Docker 容器。image 文件可以看作是容器的模板。Docker 根据 image 文件生成容器的实例。同一个 image 文件,可以生成多个同时运行的容器实例。
 *  image 文件生成的容器实例,本身也是一个文件,称为镜像文件。
 *  一个容器运行一种服务,当我们需要的时候,就可以通过docker客户端创建一个对应的运行实例,也就是我们的容器
 * 至于仓储,就是放了一堆镜像的地方,我们可以把镜像发布到仓储中,需要的时候从仓储中拉下来就可以了。
 


  安装步骤

CentOS6.8安装Docker

      yum install -y epel-release
      yum install -y docker-io
      安装后的配置文件:/etc/sysconfig/docker
      启动Docker后台服务:service docker start
      docker version验证


    CentOS7安装Docker


      https://docs.docker.com/install/linux/docker-ce/centos/
      安装步骤
        官网中文安装参考手册

          https://docs.docker-cn.com/engine/installation/linux/docker-ce/centos/#prerequisites
        确定你是CentOS7及以上版本
          cat /etc/redhat-release
        yum安装gcc相关
         

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


        卸载旧版本

 yum -y remove docker docker-common docker-selinux docker-engine

或者

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


          2018.3官网版本安装需要的软件包

yum install -y yum-utils device-mapper-persistent-data lvm2


        设置stable镜像仓库
          推荐          

yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo


        更新yum软件包索引

yum makecache fast


        安装DOCKER CE

yum -y install docker-ce

或者

yum install docker-ce docker-ce-cli containerd.io


        启动docker

systemctl start docker


        测试
         

docker version
docker run hello-world


        配置镜像加速
         

mkdir -p /etc/docker

 tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://nxezw98y.mirror.aliyuncs.com"]
}
EOF

 systemctl daemon-reload

 systemctl restart docker

开机启动docker

systemctl enable docker


        卸载
         

systemctl stop docker 
yum -y remove docker-ce
rm -rf /var/lib/docker


  永远的HelloWorld


    阿里云镜像加速
      是什么
        https://dev.aliyun.com/search.html
        获取加速器地址


      配置本机Docker运行镜像加速器

鉴于国内网络问题,后续拉取 Docker 镜像十分缓慢,我们可以需要配置加速器来解决,
我使用的是阿里云的本人自己账号的镜像地址(需要自己注册有一个属于你自己的):   https://xxxx.mirror.aliyuncs.com

 将获得的自己账户下的阿里云加速地址配置进other_args="--registry-mirror=https://你自己的账号加速信息.mirror.aliyuncs.com"

mkdir -p /etc/docker

 tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://nxezw98y.mirror.aliyuncs.com"]
}
EOF

 systemctl daemon-reload

 systemctl restart docker

或者 

vim /etc/docker/daemon.json

{
  "registry-mirrors": ["https://nxezw98y.mirror.aliyuncs.com"]
}
systemctl daemon-reload

 systemctl restart docker


 
      重新启动Docker后台服务:

service docker restart


    网易云加速
      基本同上述阿里云


    启动Docker后台容器(测试运行 hello-world)
 

[root@yangdong docker]# docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
0e03bdcc26d7: Pull complete 
Digest: sha256:6a65f928fb91fcfbc963f7aa6d57c8eeb426ad9a20c7ee045538ef34847f44f1
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

 run干了什么


  底层原理

 Docker是怎么工作的

Docker是一个Client-Server结构的系统,Docker守护进程运行在主机上, 然后通过Socket连接从客户端访问,守护进程从客户端接受命令并管理运行在主机上的容器。 容器,是一个运行时环境,就是我们前面说到的集装箱。

 为什么Docker比较比VM快

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

见解:docker镜像就是docker从dockerhub中pull过来的,类似于java的类,一个镜像可以创建多个容器,容器的存在不会依存于镜像,一旦容器创建,即使删除镜像,容器也可以运行。

查看镜像 docker images

查看容器 docker ps -a

创建容器 docker run

启动容器 docker start

删除镜像 docker rmi

删除容器 docker rm

Docker常用命令

  帮助命令


    docker version
    docker info
    docker --help


  镜像命令


    docker images
      列出本地主机上的镜像
      OPTIONS说明:
        -a :列出本地所有的镜像(含中间映像层)
        -q :只显示镜像ID。
        --digests :显示镜像的摘要信息
        --no-trunc :显示完整的镜像信息

[root@yangdong docker]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
redis               latest              4cdbec704e47        7 weeks ago         98.2MB
mysql               5.7                 413be204e9c3        7 weeks ago         456MB
hello-world         latest              bf756fb1ae65        4 months ago    


    docker search 某个XXX镜像名字
      网站
        https://hub.docker.com
      命令
        docker search [OPTIONS] 镜像名字
        OPTIONS说明:
          --no-trunc : 显示完整的镜像描述
          -s : 列出收藏数不小于指定值的镜像。
          --automated : 只列出 automated build类型的镜像;


    docker pull 某个XXX镜像名字 下载镜像  docker pull 镜像名字[:TAG]


    docker rmi 某个XXX镜像名字ID 删除镜像

删除单个docker rmi  -f 镜像ID

[root@yangdong docker]# docker rmi -f hello-world:latest 
Untagged: hello-world:latest
Untagged: hello-world@sha256:6a65f928fb91fcfbc963f7aa6d57c8eeb426ad9a20c7ee045538ef34847f44f1
Deleted: sha256:bf756fb1ae65adf866bd8c456593cd24beb6a0a061dedf42b26a993176745f6b


      删除多个 docker rmi -f 镜像名1:TAG 镜像名2:TAG 
      删除全部 docker rmi -f $(docker images -qa)

    思考
      结合我们Git的学习心得,大家猜猜是否会有 docker commit /docker push??


  容器命令


    有镜像才能创建容器,这是根本前提(下载一个CentOS镜像演示)
      docker pull centos


      docker run [OPTIONS] IMAGE [COMMAND] [ARG...] 新建并启动容器
       OPTIONS说明

OPTIONS说明(常用):有些是一个减号,有些是两个减号
 --name="容器新名字": 为容器指定一个名称;
-d: 后台运行容器,并返回容器ID,也即启动守护式容器;
-i:以交互模式运行容器,通常与 -t 同时使用;
-t:为容器重新分配一个伪输入终端,通常与 -i 同时使用;
-P: 随机端口映射;
-p: 指定端口映射,有以下四种格式
      ip:hostPort:containerPort
      ip::containerPort
      hostPort:containerPort
      containerPort

--privileged=true

大约在0.6版,privileged被引入docker。
使用该参数,container内的root拥有真正的root权限。
否则,container内的root只是外部的一个普通用户权限。
privileged启动的容器,可以看到很多host上的设备,并且可以执行mount。
甚至允许你在docker容器中启动docker容器。

        启动交互式容器

 

[root@yangdong docker]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
tomcat              latest              1b6b1fe7261e        7 days ago          647MB
redis               latest              4cdbec704e47        7 weeks ago         98.2MB
mysql               5.7                 413be204e9c3        7 weeks ago         456MB
centos              latest              470671670cac        4 months ago        237MB
[root@yangdong docker]# docker run -it centos
[root@081b2df0acdf /]# 


 

 

#使用镜像centos:latest以交互模式启动一个容器,在容器内执行/bin/bash命令。
docker run -it centos /bin/bash    

列出当前所有正在运行的容器  docker ps [OPTIONS]显示正在运行的容器
         OPTIONS说明  
-a :列出当前所有正在运行的容器+历史上运行过的
-l :显示最近创建的容器。
-n:显示最近n个创建的容器。
-q :静默模式,只显示容器编号。
--no-trunc :不截断输出。

       exit容器停止退出


      ctrl+P+Q    容器不停止退出

docker start 容器ID或者容器名    启动容器
     

  docker restart 容器ID或者容器名    重启容器
   

  docker stop 容器ID或者容器名    停止容器
   

      docker kill 容器ID或者容器名    强制停止容器

      docker rm 容器ID  删除已停止的容器

    docker rm -f $(docker ps -a -q)
    docker ps -a -q | xargs docker rm
   一次性删除多个容器
         
    重要

docker run -d 容器名     启动守护式容器

#使用镜像centos:latest以后台模式启动一个容器
docker run -d centos
 问题:然后docker ps -a 进行查看, 会发现容器已经退出
很重要的要说明的一点: Docker容器后台运行,就必须有一个前台进程.
容器运行的命令如果不是那些一直挂起的命令(比如运行top,tail),就是会自动退出的。
 这个是docker的机制问题,比如你的web容器,我们以nginx为例,正常情况下,我们配置启动服务只需要启动响应的service即可。例如
service nginx start
但是,这样做,nginx为后台进程模式运行,就导致docker前台没有运行的应用,
这样的容器后台启动后,会立即自杀因为他觉得他没事可做了.
所以,最佳的解决方案是,将你要运行的程序以前台进程的形式运行

启动守护式容器后容器自动关闭

[root@yangdong ~]# docker run -d --name="centos1" centos
e553833e14ee8ba5cbb01ca9c529833e36acff48fb53e0be1ba87987ab20fa6e

[root@yangdong ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
[root@yangdong ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS                          PORTS               NAMES
e553833e14ee        centos              "/bin/bash"              About a minute ago   Exited (0) About a minute ago                       centos1
72604b72fef0        centos              "/bin/bash"              28 minutes ago       Exited (127) 26 minutes ago                         centos0
87e902723d74        centos              "-it -name=centos0"      30 minutes ago       Created                                             sad_kalam
081b2df0acdf        centos              "/bin/bash"              54 minutes ago       Exited (0) 45 seconds ago                           dazzling_carson


        docker logs -f -t --tail 容器ID    查看容器日志
          *   -t 是加入时间戳
          *   -f 跟随最新的日志打印
          *   --tail 数字 显示最后多少条

启动守护式容器并且每隔2秒打印一句话容器则不会自动退出docker run -d centos /bin/sh -c "while true;do echo hello zzyy;sleep 2;done"

[root@yangdong ~]# docker run -d --name="centos3" centos /bin/bash -c "while true;do echo hello zzyy;sleep 2;done"
6ecfce9a30e496ae57e79c6c88060ba1867e7de227ac420a698566b9942b53d3
[root@yangdong ~]# docker logs -tf --tail 10 centos3
2020-05-23T19:38:47.112419595Z hello zzyy
2020-05-23T19:38:49.116200945Z hello zzyy
2020-05-23T19:38:51.120568593Z hello zzyy
2020-05-23T19:38:53.124790406Z hello zzyy
^C
[root@yangdong ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
6ecfce9a30e4        centos              "/bin/bash -c 'while…"   2 minutes ago       Up 2 minutes                            centos3


     
        docker top 容器ID  查看容器内运行的进程

[root@yangdong ~]# docker top 6ecfce9a30e4
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                16749               16734               0                   03:37               ?                   00:00:00            /bin/bash -c while true;do echo hello zzyy;sleep 2;done
root                17668               16749               0                   03:54               ?                   00:00:00            /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 2


        docker inspect 容器ID  查看容器内部细节
 

[root@yangdong ~]# docker inspect 6ecfce9a30e4
[
    {
        "Id": "6ecfce9a30e496ae57e79c6c88060ba1867e7de227ac420a698566b9942b53d3",
        "Created": "2020-05-23T19:37:25.297639643Z",
        "Path": "/bin/bash",
        "Args": [
            "-c",
            "while true;do echo hello zzyy;sleep 2;done"
        ],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 16749,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2020-05-23T19:37:26.829229586Z",
            "FinishedAt": "0001-01-01T00:00:00Z"
        },
        "Image": "sha256:470671670cac686c7cf0081e0b37da2e9f4f768ddc5f6a26102ccd1c6954c1ee",
        "ResolvConfPath": "/var/lib/docker/containers/6ecfce9a30e496ae57e79c6c88060ba1867e7de227ac420a698566b9942b53d3/resolv.conf",
        "HostnamePath": "/var/lib/docker/containers/6ecfce9a30e496ae57e79c6c88060ba1867e7de227ac420a698566b9942b53d3/hostname",
        "HostsPath": "/var/lib/docker/containers/6ecfce9a30e496ae57e79c6c88060ba1867e7de227ac420a698566b9942b53d3/hosts",
        "LogPath": "/var/lib/docker/containers/6ecfce9a30e496ae57e79c6c88060ba1867e7de227ac420a698566b9942b53d3/6ecfce9a30e496ae57e79c6c88060ba1867e7de227ac420a698566b9942b53d3-json.log",
        "Name": "/centos3",
        "RestartCount": 0,
        "Driver": "overlay2",
        "Platform": "linux",


        docker exec -it 容器ID bashShell 进入正在运行的容器并以命令行交互

       docker attach 容器ID 重新进入
        上述两个区别
          attach 直接进入容器启动命令的终端,不会启动新的进程
          exec 是在容器中打开新的终端,并且可以启动新的进程,exec可以直接获取执行结果而不必进入系统

[root@yangdong ~]# docker exec 6ecfce9a30e4 ls /
bin
dev
etc
home
lib
lib64
lost+found
media
mnt
opt
proc
root


        docker cp  容器ID:容器内路径 目的主机路径 从容器内拷贝文件到主机上

  小总结
    常用命令

attach    Attach to a running container                 # 当前 shell 下 attach 连接指定运行镜像


build     Build an image from a Dockerfile              # 通过 Dockerfile 定制镜像


commit    Create a new image from a container changes   # 提交当前容器为新的镜像


cp        Copy files/folders from the containers filesystem to the host path   #从容器中拷贝指定文件或者目录到宿主机中


create    Create a new container                        # 创建一个新的容器,同 run,但不启动容器


diff      Inspect changes on a container's filesystem   # 查看 docker 容器变化


events    Get real time events from the server          # 从 docker 服务获取容器实时事件


exec      Run a command in an existing container        # 在已存在的容器上运行命令


export    Stream the contents of a container as a tar archive   # 导出容器的内容流作为一个 tar 归档文件[对应 import ]


history   Show the history of an image                  # 展示一个镜像形成历史


images    List images                                   # 列出系统当前镜像


import    Create a new filesystem image from the contents of a tarball # 从tar包中的内容创建一个新的文件系统映像[对应export]


info      Display system-wide information               # 显示系统相关信息


inspect   Return low-level information on a container   # 查看容器详细信息


kill      Kill a running container                      # kill 指定 docker 容器


load      Load an image from a tar archive              # 从一个 tar 包中加载一个镜像[对应 save]


login     Register or Login to the docker registry server    # 注册或者登陆一个 docker 源服务器


logout    Log out from a Docker registry server          # 从当前 Docker registry 退出


logs      Fetch the logs of a container                 # 输出当前容器日志信息


port      Lookup the public-facing port which is NAT-ed to PRIVATE_PORT    # 查看映射端口对应的容器内部源端口


pause     Pause all processes within a container        # 暂停容器


ps        List containers                               # 列出容器列表


pull      Pull an image or a repository from the docker registry server   # 从docker镜像源服务器拉取指定镜像或者库镜像


push      Push an image or a repository to the docker registry server    # 推送指定镜像或者库镜像至docker源服务器


restart   Restart a running container                   # 重启运行的容器


rm        Remove one or more containers                 # 移除一个或者多个容器


rmi       Remove one or more images             # 移除一个或多个镜像[无容器使用该镜像才可删除,否则需删除相关容器才可继续或 -f 强制删除]


run       Run a command in a new container              # 创建一个新的容器并运行一个命令


save      Save an image to a tar archive                # 保存一个镜像为一个 tar 包[对应 load]


search    Search for an image on the Docker Hub         # 在 docker hub 中搜索镜像


start     Start a stopped containers                    # 启动容器


stop      Stop a running containers                     # 停止容器


tag       Tag an image into a repository                # 给源中镜像打标签


top       Lookup the running processes of a container   # 查看容器中运行的进程信息


unpause   Unpause a paused container                    # 取消暂停容器


version   Show the docker version information           # 查看 docker 版本号


wait      Block until a container stops, then print its exit code   # 截取容器停止时的退出状态值
 

Docker 镜像

  是什么


    UnionFS(联合文件系统)

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

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

     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就是各种不同的操作系统发行版,比如Ubuntu,Centos等等。 

    分层的镜像

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就是各种不同的操作系统发行版,比如Ubuntu,Centos等等。 

平时我们安装进虚拟机的CentOS都是好几个G,为什么docker这里才200M??

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



    为什么 Docker 镜像要采用这种分层结构呢

最大的一个好处就是 - 共享资源
 
比如:有多个镜像都从相同的 base 镜像构建而来,那么宿主机只需在磁盘上保存一份base镜像,
同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。
 


  特点


    Docker镜像都是只读的 当容器启动时,一个新的可写层被加载到镜像的顶部。 这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。


  Docker镜像commit操作补充


    docker commit提交容器副本使之成为一个新的镜像
    docker commit -m=“提交的描述信息” -a=“作者” 容器ID 要创建的目标镜像名:[标签名]
    案例演示
      从Hub上下载tomcat镜像到本地并成功运行


        docker run -it -p 8080:8080 tomcat
          -p 主机端口:docker容器端口
          -P 随机分配端口

root@ccc42c3a5b3b:/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@ccc42c3a5b3b:/usr/local/tomcat# cd webapps
root@ccc42c3a5b3b:/usr/local/tomcat/webapps# ls

 注意:启动tomcat后无法访问主页是因为webapps文件夹是空的,把webapps.dist文件夹中的文件复制一份到webapps中重启tomcat就可以访问主页了

 


          i:交互
          t:终端
      故意删除上一步镜像生产tomcat容器的文档

 


      也即当前的tomcat运行实例是一个没有文档内容的容器, 以它为模板commit一个没有doc的tomcat新镜像atguigu/tomcat02

[root@yangdong ~]# docker commit -a="yangdong" -m="tomcat without docs" ccc42c3a5b3b yangdong/tomcat
sha256:57357b86335b8a0eaf1c51c01ee75122aefe0089a0ebc3ee809e463016b1d7da
[root@yangdong ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
yangdong/tomcat     latest              57357b86335b        12 seconds ago      531MB
tomcat              8                   f19c56ce92a8        7 days ago          529MB
redis               latest              4cdbec704e47        7 weeks ago         98.2MB
mysql               5.7                 413be204e9c3        7 weeks ago         456MB
centos              latest              470671670cac        4 months ago        237MB

     

启动我们的新镜像并和原来的对比
        启动atguigu/tomcat02,它没有docs


        新启动原来的tomcat,它有docs

 

Docker容器数据卷

  是什么

先来看看Docker的理念:
*  将运用与运行的环境打包形成容器运行 ,运行可以伴随着容器,但是我们对数据的要求希望是持久化的
*  容器之间希望有可能共享数据
Docker容器产生的数据,如果不通过docker commit生成新的镜像,使得数据做为镜像的一部分保存下来,
那么当容器删除后,数据自然也就没有了。
 
为了能保存数据在docker中我们使用卷
    一句话:有点类似我们Redis里面的rdb和aof文件


  能干嘛

卷就是目录或文件,存在于一个或多个容器中,由docker挂载到容器,但不属于联合文件系统,因此能够绕过Union File System提供一些用于持续存储或共享数据的特性:
 卷的设计目的就是数据的持久化,完全独立于容器的生存周期,因此Docker不会在容器删除时删除其挂载的数据卷
特点:
1:数据卷可在容器之间共享或重用数据
2:卷中的更改可以直接生效
3:数据卷中的更改不会包含在镜像的更新中
4:数据卷的生命周期一直持续到没有容器使用它为止
    容器的持久化
    容器间继承+共享数据


  数据卷容器内添加


      1.直接命令添加


        命令  docker run -it -v /宿主机绝对路径目录:/容器内目录      镜像名


        查看数据卷是否挂载成功 docker inspect 容器ID

        容器和宿主机之间数据共享


        容器停止退出后,主机修改后数据同步


        命令(带权限) docker run -it -v /宿主机绝对路径目录:/容器内目录:ro 镜像名 ,ro是readonly的缩写


      2.DockerFile添加


        根目录下新建mydocker文件夹并进入


        可在Dockerfile中使用VOLUME指令来给镜像添加一个或多个数据卷VOLUME["/dataVolumeContainer","/dataVolumeContainer2","/dataVolumeContainer3"]
 
说明:出于可移植和分享的考虑,用-v 主机目录:容器目录这种方法不能够直接在Dockerfile中实现。
由于宿主机目录是依赖于特定宿主机的,并不能够保证在所有的宿主机上都存在这样的特定目录。

        File构建

# volume test
FROM centos
VOLUME ["/dataVolumeContainer1","/dataVolumeContainer2"]
CMD echo "finished,--------success1"
CMD /bin/bash


        build后生成镜像 获得一个新镜像zzyy/centos


        run容器


        通过上述步骤,容器内的卷目录地址已经知道 对应的主机目录地址哪??


        主机对应默认地址


[root@yangdong /]# mkdir dockerfile
[root@yangdong /]# cd /dockerfile/
[root@yangdong dockerfile]# vim dockerfile0

# volume test
FROM centos
VOLUME ["/datavolumecontainer","/datavolumecontainer1"]
CMD echo "finished"
CMD /bin/bash

[root@yangdong dockerfile]# docker build -f /dockerfile/dockerfile0 -t ysangdong/centos .

Successfully built a63a54be0ceb
Successfully tagged ysangdong/centos:latest



[root@yangdong dockerfile]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ysangdong/centos    latest              a63a54be0ceb        10 seconds ago      237MB

[root@yangdong dockerfile]# docker run -it  a63a54be0ceb
[root@60b59d8ba2c8 /]# ls
bin  datavolumecontainer  datavolumecontainer1	dev  etc  home	lib  lib64  lost+found	media  mnt  opt  proc  root  run  sbin	srv  sys  tmp  usr  var

[root@yangdong dockerfile]# docker inspect 60b59d8ba2c8

    "Mounts": [
            {
                "Type": "volume",
                "Name": "f5bf2e065d80b88d7f3f75759fecfcd5dd8edc27e27ae59a3b376f8aa1259569",
                "Source": "/var/lib/docker/volumes/f5bf2e065d80b88d7f3f75759fecfcd5dd8edc27e27ae59a3b376f8aa1259569/_data",
                "Destination": "/datavolumecontainer",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            },
            {
                "Type": "volume",
                "Name": "48c1e86795a9c3c5162b5edc4d0a9ce171caf4f39cd9abbde93ebd7993d826bb",
                "Source": "/var/lib/docker/volumes/48c1e86795a9c3c5162b5edc4d0a9ce171caf4f39cd9abbde93ebd7993d826bb/_data",
                "Destination": "/datavolumecontainer1",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],


注意:编辑dockerfile的时候没有指定宿主机绑定的目录位置,docker会自动生成一个目录来绑定容器内的卷目录,docker inspect 60b59d8ba2c8命令生成的详细信息中mount数组就是docker在宿主机中自动生成的目录     

备注

Docker挂载主机目录Docker访问出现cannot open directory .: Permission denied
解决办法:在挂载目录后多加一个--privileged=true参数即可,该参数可以提高权限

VOLUME  和-v 映射的都只是目录



  数据卷容器

命名的容器挂载数据卷,其它容器通过挂载这个(父容器)实现数据共享,挂载数据卷的容器,称之为数据卷容器



      以上一步新建的镜像zzyy/centos为模板并运行容器dc01/dc02/dc03


    容器间传递共享(--volumes-from)


      先启动一个父容器dc01 在dataVolumeContainer2新增内容


      dc02/dc03继承自dc01 --volumes-from
        命令 docker run -it --name dc02 --volumes-from dc01 zzyy/centos  

dc02/dc03分别在dataVolumeContainer2各自新增内容


      回到dc01可以看到02/03各自添加的都能共享了


      删除dc01,dc02修改后dc03可否访问


      删除dc02后dc03可否访问


        再进一步


      新建dc04继承dc03后再删除dc03


  同一个镜像创造出来的容器如果没有继承关系,他们不能共享数据,也就是说他们的宿主机映射目录不同

[root@yangdong dockerfile]# docker run -it --name dc01 a63a54be0ceb
[root@8948e1e79ff5 /]# ls
bin  datavolumecontainer  datavolumecontainer1	dev  etc  home	lib  lib64  lost+found	media  mnt  opt  proc  root  run  sbin	srv  sys  tmp  usr  var
[root@8948e1e79ff5 /]# cd datavolumecontainer
[root@8948e1e79ff5 datavolumecontainer]# touch dc01.txt
[root@8948e1e79ff5 datavolumecontainer]# ls
dc01.txt

[root@yangdong ~]# docker run -it --name dc02 a63a54be0ceb
[root@e15eafafe633 /]# ls
bin  datavolumecontainer  datavolumecontainer1	dev  etc  home	lib  lib64  lost+found	media  mnt  opt  proc  root  run  sbin	srv  sys  tmp  usr  var
[root@e15eafafe633 /]# cd datavolumecontainer
[root@e15eafafe633 datavolumecontainer]# touch dc02.txt
[root@e15eafafe633 datavolumecontainer]# ls
dc02.txt

[root@yangdong ~]# docker inspect dc02
        "Mounts": [
            {
                "Type": "volume",
                "Name": "46cdee2235a22a84add27f31ff2eea429a66cb3c8a65f2cd857d95a253c7120c",
                "Source": "/var/lib/docker/volumes/46cdee2235a22a84add27f31ff2eea429a66cb3c8a65f2cd857d95a253c7120c/_data",
                "Destination": "/datavolumecontainer",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            },
            {
                "Type": "volume",
                "Name": "eefb056d46657264592906401532f2a3d3b374bf79def26570995cdf0e937e52",
                "Source": "/var/lib/docker/volumes/eefb056d46657264592906401532f2a3d3b374bf79def26570995cdf0e937e52/_data",
                "Destination": "/datavolumecontainer1",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ]

[root@yangdong ~]# docker inspect dc01
 "Mounts": [
            {
                "Type": "volume",
                "Name": "9dbe73b7adb0e83198e4d330ff005d273fafac7a2b34449511e94e3a74f18a7e",
                "Source": "/var/lib/docker/volumes/9dbe73b7adb0e83198e4d330ff005d273fafac7a2b34449511e94e3a74f18a7e/_data",
                "Destination": "/datavolumecontainer",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            },
            {
                "Type": "volume",
                "Name": "b2d85da8731435517fcb3295eb0221028e523b8d8b9107a85bec69c8f9b1b005",
                "Source": "/var/lib/docker/volumes/b2d85da8731435517fcb3295eb0221028e523b8d8b9107a85bec69c8f9b1b005/_data",
                "Destination": "/datavolumecontainer1",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],

   如果 同一个镜像创造出来的容器有了继承关系 --volumes-from,他们就会有共同的宿主机映射目录


[root@yangdong ~]# docker run -it --name dc03 --volumes-from dc01 a63a54be0ceb
[root@b17ed8efd19d /]# cd /datavolumecontainer
[root@b17ed8efd19d datavolumecontainer]# ls
dc01.txt

[root@yangdong ~]# docker inspect dc03

"Mounts": [
            {
                "Type": "volume",
                "Name": "b2d85da8731435517fcb3295eb0221028e523b8d8b9107a85bec69c8f9b1b005",
                "Source": "/var/lib/docker/volumes/b2d85da8731435517fcb3295eb0221028e523b8d8b9107a85bec69c8f9b1b005/_data",
                "Destination": "/datavolumecontainer1",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            },
            {
                "Type": "volume",
                "Name": "9dbe73b7adb0e83198e4d330ff005d273fafac7a2b34449511e94e3a74f18a7e",
                "Source": "/var/lib/docker/volumes/9dbe73b7adb0e83198e4d330ff005d273fafac7a2b34449511e94e3a74f18a7e/_data",
                "Destination": "/datavolumecontainer",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],

[root@yangdong ~]# docker inspect dc01
 "Mounts": [
            {
                "Type": "volume",
                "Name": "9dbe73b7adb0e83198e4d330ff005d273fafac7a2b34449511e94e3a74f18a7e",
                "Source": "/var/lib/docker/volumes/9dbe73b7adb0e83198e4d330ff005d273fafac7a2b34449511e94e3a74f18a7e/_data",
                "Destination": "/datavolumecontainer",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            },
            {
                "Type": "volume",
                "Name": "b2d85da8731435517fcb3295eb0221028e523b8d8b9107a85bec69c8f9b1b005",
                "Source": "/var/lib/docker/volumes/b2d85da8731435517fcb3295eb0221028e523b8d8b9107a85bec69c8f9b1b005/_data",
                "Destination": "/datavolumecontainer1",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],

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

 

DockerFile解析

  是什么


    Dockerfile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本。
    构建三步骤  编写Dockerfile文件        docker build          docker run

    


  DockerFile构建过程解析


    Dockerfile内容基础知识
      1:每条保留字指令都必须为大写字母且后面要跟随至少一个参数
      2:指令按照从上到下,顺序执行
      3:#表示注释
      4:每条指令都会创建一个新的镜像层,并对镜像进行提交
    Docker执行Dockerfile的大致流程
      (1)docker从基础镜像运行一个容器
      (2)执行一条指令并对容器作出修改
      (3)执行类似docker commit的操作提交一个新的镜像层
      (4)docker再基于刚提交的镜像运行一个新容器
      (5)执行dockerfile中的下一条指令直到所有指令都执行完成
    小总结

从应用软件的角度来看,Dockerfile、Docker镜像与Docker容器分别代表软件的三个不同阶段,
*  Dockerfile是软件的原材料
*  Docker镜像是软件的交付品
*  Docker容器则可以认为是软件的运行态。
Dockerfile面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可,合力充当Docker体系的基石。

1 Dockerfile,需要定义一个Dockerfile,Dockerfile定义了进程需要的一切东西。Dockerfile涉及的内容包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程(当应用进程需要和系统服务和内核进程打交道,这时需要考虑如何设计namespace的权限控制)等等;
 
2 Docker镜像,在用Dockerfile定义一个文件之后,docker build时会产生一个Docker镜像,当运行 Docker镜像时,会真正开始提供服务;
 
3 Docker容器,容器是直接提供服务的。
 


  DockerFile体系结构(保留字指令)


    FROM      基础镜像,当前新镜像是基于哪个镜像的


    MAINTAINER      镜像维护者的姓名和邮箱地址


    RUN     容器构建时需要运行的命令


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


    WORKDIR      指定在创建容器后,终端默认登陆的进来工作目录,一个落脚点


    ENV      用来在构建镜像过程中设置环境变量  ENV MY_PATH  /usr/mytest(key value)这个环境变量可以在后续的任何RUN指令中使用,这就如同在命令前面指定了环境变量前缀一样;也可以在其它指令中直接使用这些环境变量,比如:WORKDIR $MY_PATH

    ADD      将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL和解压tar压缩包


    COPY      类似ADD,拷贝文件和目录到镜像中。 将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置        COPY src dest        COPY ["src", "dest"]


    VOLUME      容器数据卷,用于数据保存和持久化工作


    CMD      指定一个容器启动时要运行的命令      Dockerfile 中可以有多个 CMD 指令,但只有最后一个生效,CMD 会被 docker run 之后的参数替换


    ENTRYPOINT       指定一个容器启动时要运行的命令      ENTRYPOINT 的目的和 CMD 一样,都是在指定容器启动程序及参数


    ONBUILD      当构建一个被继承的Dockerfile时运行命令,父镜像在被子继承后父镜像的onbuild被触发


   

小总结


    Base镜像(scratch)


      Docker Hub 中 99% 的镜像都是通过在 base 镜像中安装和配置需要的软件构建出来的

FROM scratch
ADD centos-7-x86_64-docker.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="20200504" \
    org.opencontainers.image.title="CentOS Base Image" \
    org.opencontainers.image.vendor="CentOS" \
    org.opencontainers.image.licenses="GPL-2.0-only" \
    org.opencontainers.image.created="2020-05-04 00:00:00+01:00"

CMD ["/bin/bash"]

scratch镜像就是源镜像


    自定义镜像mycentos


      编写


        Hub默认CentOS镜像什么情况

自定义mycentos目的使我们自己的镜像具备如下:
         登陆后的默认路径
         vim编辑器
         查看网络配置ifconfig支持



        准备编写DockerFile文件


        myCentOS内容DockerFile

FROM centos
MAINTAINER zzyy<zzyy167@126.com>
 
ENV MYPATH /usr/local
WORKDIR $MYPATH
 
RUN yum -y install vim
RUN yum -y install net-tools
 
EXPOSE 80
 
CMD echo $MYPATH
CMD echo "success--------------ok"
CMD /bin/bash


   

  构建


        docker build -f dockerfile目录 -t 新镜像名字:TAG .

会看到 docker build 命令最后有一个 .     . 表示当前目录

 



 

    运行


        docker run -it 新镜像名字:TAG 

可以看到,我们自己的新镜像已经支持vim/ifconfig命令,扩展成功了。

     

列出镜像的变更历史


        docker history 镜像名:是dockerfile的执行过程,从下往上执行

[root@yangdong dockerfile]# docker history centos
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
470671670cac        4 months ago        /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B                  
<missing>           4 months ago        /bin/sh -c #(nop)  LABEL org.label-schema.sc…   0B                  
<missing>           4 months ago        /bin/sh -c #(nop) ADD file:aa54047c80ba30064…   237MB     
          
[root@yangdong dockerfile]# docker history yangdong/centos
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
f145a9e2c004        6 minutes ago       /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "/bin…   0B                  
242ef0c2c3cc        6 minutes ago       /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "echo…   0B                  
3a56f0dd746d        6 minutes ago       /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "echo…   0B                  
6b77478e4feb        6 minutes ago       /bin/sh -c #(nop)  EXPOSE 80                    0B                  
2c2b9c933999        6 minutes ago       /bin/sh -c yum -y install net-tools             24.1MB              
9165d9c50364        6 minutes ago       /bin/sh -c yum -y install vim                   59.8MB              
124195da6063        6 minutes ago       /bin/sh -c #(nop) WORKDIR /usr/local            0B                  
76be82733f0c        6 minutes ago       /bin/sh -c #(nop)  ENV MYPATH=/usr/local        0B                  
c5d5aa177bb9        6 minutes ago       /bin/sh -c #(nop)  MAINTAINER zzyy<zzyy167@1…   0B                  
470671670cac        4 months ago        /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B                  
<missing>           4 months ago        /bin/sh -c #(nop)  LABEL org.label-schema.sc…   0B                  
<missing>           4 months ago        /bin/sh -c #(nop) ADD file:aa54047c80ba30064…   237MB 


    CMD/ENTRYPOINT 镜像案例


      都是指定一个容器启动时要运行的命令


      CMD      Dockerfile 中可以有多个 CMD 指令,但只有最后一个生效,CMD 会被 docker run 之后的参数替换   


      ENTRYPOINT         docker run 之后的参数会被当做参数传递给 ENTRYPOINT,之后形成新的命令组合


    制作CMD版可以查询IP信息的容器            crul命令解释

FROM centos
RUN yum install -y curl
CMD [ "curl", "-s", "http://ip.cn" ]

curl命令可以用来执行下载、发送各种HTTP请求,指定HTTP头部等操作。
如果系统没有curl可以使用yum install curl安装,也可以下载安装。
curl是将下载文件输出到stdout
 
使用命令:curl http://www.baidu.com
执行后,www.baidu.com的html就会显示在屏幕上了


  如果我们希望显示 HTTP 头信息,就需要加上 -i 参数,制作ENTROYPOINT版查询IP信息的容器


 

我们可以看到可执行文件找不到的报错,executable file not found。
之前我们说过,跟在镜像名后面的是 command,运行时会替换 CMD 的默认值。
因此这里的 -i 替换了原来的 CMD,而不是添加在原来的 curl -s http://ip.cn 后面。而 -i 根本不是命令,所以自然找不到。
 那么如果我们希望加入 -i 这参数,我们就必须重新完整的输入这个命令:

FROM centos
RUN yum install -y curl
ENTRYPOINT [ "curl", "-s", "http://ip.cn" ]

 重新build

[root@yangdong dockerfile]# docker build -f /dockerfile/dockerfile2 -t curl2/centos .

添加参数执行

[root@yangdong dockerfile]# docker run curl2/centos -i
HTTP/1.1 200 OK
Accept-Ranges: bytes
Cache-Control: private, no-cache, no-store, proxy-revalidate, no-transform
Connection: keep-alive
Content-Length: 2381
Content-Type: text/html
Date: Thu, 28 May 2020 04:31:56 GMT
Etag: "588604c8-94d"
Last-Modified: Mon, 23 Jan 2017 13:27:36 GMT
Pragma: no-cache
Server: bfe/1.0.8.18

ONBUILD      当构建一个被继承的Dockerfile时运行命令,父镜像在被子继承后父镜像的onbuild被触发

FROM centos
RUN yum install -y curl
ENTRYPOINT [ "curl", "-s", "http://ip.cn" ]
ONBUILD RUN echo "father images onbuild---886"

重新build

[root@yangdong dockerfile]# docker build -f /dockerfile/dockerfile2 -t father/centos .

 继承father镜像

FROM father/centos
RUN echo "child is build"
EXPOSE 8080
ENTRYPOINT ["curl","-s","http://www.qq.com"]

build chuild ,run child

[root@yangdong dockerfile]# docker build -f /dockerfile/dockerfile3 -t child/centos .
Sending build context to Docker daemon   5.12kB
Step 1/4 : FROM father/centos
# Executing 1 build trigger
 ---> Running in af095f736cee
father is onbuild--886

[root@yangdong dockerfile]# docker run child/centos
<html>
<head><title>302 Found</title></head>
<body bgcolor="white">
<center><h1>302 Found</h1></center>
<hr><center>nginx</center>
</body>
</html>

 

注意:每修改一次dockerfile就要重新build一次镜像,这样修改的dockerfile才会起作用,子镜像不会继承父镜像的CMD

ENTRYPOINT 

 

解决报错WARNING: IPv4 forwarding is disabled. Networking will not work.

[root@yangdong dockerfile]# docker run -it curl/centos
WARNING: IPv4 forwarding is disabled. Networking will not work.

第一步:在宿主机上执行echo "net.ipv4.ip_forward=1" >>/usr/lib/sysctl.d/00-system.conf 或者使用vim命令在00-system.conf的最后一行添加net.ipv4.ip_forward=1,这行代码的作用是开启路由功能。

echo "net.ipv4.ip_forward=1" >>/usr/lib/sysctl.d/00-system.conf

第二步:重启network和docker服务

[root@localhost /]# systemctl restart network && systemctl restart docker

 


    自定义镜像Tomcat9


     1. mkdir -p /zzyyuse/mydockerfile/tomcat9
     2. 在上述目录下touch c.txt
     3. 将jdk和tomcat安装的压缩包拷贝进上一步目录

        apache-tomcat-9.0.8.tar.gz


        jdk-8u171-linux-x64.tar.gz


 4.     在/zzyyuse/mydockerfile/tomcat9目录下新建Dockerfile文件        目录内容

FROM         centos
MAINTAINER    zzyy<zzyybs@126.com>
#把宿主机当前上下文的c.txt拷贝到容器/usr/local/路径下
COPY c.txt /usr/local/cincontainer.txt
#把java与tomcat添加到容器中
ADD jdk-8u171-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-9.0.8.tar.gz /usr/local/
#安装vim编辑器
RUN yum -y install vim
#设置工作访问时候的WORKDIR路径,登录落脚点
ENV MYPATH /usr/local
WORKDIR $MYPATH
#配置java与tomcat环境变量
ENV JAVA_HOME /usr/local/jdk1.8.0_171
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.8
ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.8
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
#容器运行时监听的端口
EXPOSE  8080
#启动时运行tomcat
# ENTRYPOINT ["/usr/local/apache-tomcat-9.0.8/bin/startup.sh" ]
# CMD ["/usr/local/apache-tomcat-9.0.8/bin/catalina.sh","run"]
CMD /usr/local/apache-tomcat-9.0.8/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.8/bin/logs/catalina.out


 5.     构建        构建完成


     

6.run        备注


    7.  验证


      结合前述的容器卷将测试的web服务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_2_5.xsd"
  id="WebApp_ID" version="2.5">
  
  <display-name>test</display-name>
 
</web-app>


        a.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
  </head>
  <body>
    -----------welcome------------
    <%="i am in docker tomcat self "%>
    <br>
    <br>
    <% System.out.println("=============docker tomcat self");%>
  </body>
</html>
 

        测试

[root@yangdong tomcat]# cd test/
[root@yangdong test]# mkdir WEB-INF
[root@yangdong test]# cd WEB-INF/
[root@yangdong WEB-INF]# vim web.xml
[root@yangdong WEB-INF]# cd ..
[root@yangdong test]# vim a.jsp
[root@yangdong test]# docker restart myt9
myt9
[root@yangdong test]# ls
a.jsp  WEB-INF
[root@yangdong test]# cd ..
[root@yangdong tomcat]# ls
apache-tomcat-8.5.55.tar.gz  c.txt  dockerfile3  jdk-8u11-linux-x64.tar.gz  test  tomcatlogs
[root@yangdong tomcat]# cd tomcatlogs/
[root@yangdong tomcatlogs]# ls
catalina.2020-05-29.log  host-manager.2020-05-29.log  localhost_access_log.2020-05-29.txt
catalina.out             localhost.2020-05-29.log     manager.2020-05-29.log
[root@yangdong tomcatlogs]# cat catalina.out 
29-May-2020 12:25:51.685 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server version name:   Apache Tomcat/8.5.55...........
29-May-2020 12:44:27.819 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in 943 ms
=============docker tomcat self
docker run -d -p 9080:8080 --name myt9 -v /zzyyuse/mydockerfile/tomcat9/test:/usr/local/apache-tomcat-9.0.8/webapps/test -v /zzyyuse/mydockerfile/tomcat9/tomcat9logs/:/usr/local/apache-tomcat-9.0.8/logs --privileged=true zzyytomcat9

小总结

Docker常用安装

  总体步骤

    搜索镜像
    拉取镜像
    查看镜像
    启动镜像
    停止容器
    移除容器


  安装tomcat


    docker hub上面查找tomcat镜像   docker search tomcat


    从docker hub上拉取tomcat镜像到本地      docker pull tomcat


    docker images查看是否有拉取到的tomcat


    使用tomcat镜像创建容器(也叫运行镜像      docker run -it -p 8080:8080 tomcat    -p 主机端口:docker容器端口       -P 随机分配端口       -i:交互        -t:终端(一般-i,-t结合使用)

  安装mysql


    docker hub上面查找mysql镜像    从docker hub上(阿里云加速器)拉取mysql镜像到本地标签为5.6


    使用mysql5.6镜像创建容器(也叫运行镜像)     使用mysql镜像

docker run -p 12345:3306 --name mysql -v /zzyyuse/mysql/conf:/etc/mysql/conf.d -v /zzyyuse/mysql/logs:/logs -v /zzyyuse/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.6

命令说明:
-p 12345:3306:将主机的12345端口映射到docker容器的3306端口。
--name mysql:运行服务名字
-v /zzyyuse/mysql/conf:/etc/mysql/conf.d :将主机/zzyyuse/mysql/conf/ 挂载到容器的 /etc/mysql/conf.d
-v /zzyyuse/mysql/logs:/logs:将主机/zzyyuse/mysql/logs 目录挂载到容器的 /logs。
-v /zzyyuse/mysql/data:/var/lib/mysql :将主机/zzyyuse/mysql/data目录挂载到容器的 /var/lib/mysql 
-e MYSQL_ROOT_PASSWORD=123456:初始化 root 用户的密码。
-d mysql:5.6 : 后台程序运行mysql5.6

注意:-v 指令宿主机

docker exec -it MySQL运行成功后的容器ID     /bin/bash



    数据备份小测试

docker exec myql服务容器ID sh -c ' exec mysqldump --all-databases -uroot -p"123456" ' > /zzyyuse/all-databases.sql


  安装redis

    从docker hub上(阿里云加速器)拉取redis镜像到本地标签为3.2


    使用redis3.2镜像创建容器(也叫运行镜像)      使用镜像

docker run -p 6379:6379 --name=redis -v /myredis/data:/data -v /myredis/conf:/usr/local/etc/redis  -d redis redis-server /usr/local/etc/redis/redis.conf --appendonly yes


      在主机/zzyyuse/myredis/conf/redis.conf目录下新建redis.conf文件

      vim /zzyyuse/myredis/conf/redis.conf/redis.conf

运行 redis

docker exec -it redis redis-cli

开启 aof 持久化

vi /mydata/redis/conf/redis.conf # 添加如下内容 appendonly yes

重启 redis

docker restart redis

-v只能映射目录,不能映射文件

 


      测试redis-cli连接上来

docker exec -it 运行着Rediis服务的容器ID redis-cli


      测试持久化文件生成

本地镜像发布到阿里云


  本地镜像发布到阿里云流程


  镜像的生成方法

 前面的DockerFile
 从容器创建一个新的镜像 docker commit [OPTIONS] 容器ID [REPOSITORY[:TAG]]

OPTIONS说明:
-a :提交的镜像作者;
-m :提交时的说明文字;


  将本地镜像推送到阿里云


    本地镜像素材原型


    阿里云开发者平台      https://dev.aliyun.com/search.html
    创建仓库镜像    命名空间      仓库名称


    将镜像推送到registry


    公有云可以查询到


    查看详情


  将阿里云上的镜像下载到本地  下载到本地

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值