Docker入门

作者: CaiGuangyin | 来源:发表于2018-04-15 23:03 被阅读224次

    Docker入门

    Docker命令官方示例

    [toc]

    1. Docker架构

    1.1 Docker镜像与Docker容器的关系

    父与子的关系,用Docker镜像来创建Docker窗口;也类似于面向对象中类(镜像)与对象(容器)的关系。

    Docker 面向对象
    容器 对象
    镜像
    image.png
    名字 解释
    Docker镜像(Images) Docker镜像是用于创建Docker容器的模板
    Docker容器(Container) 容器是独立运行的一个或一组应用。
    Docker客户端(Client) Docker客户端通过命令行或者其他工具使用Docker API与Docker守护进程通信。
    Docker主机(Host) 一个物理或者虚拟的机器用于执行Docker守护进程和容器。
    Docker仓库(Registry) Docker仓库用来保存镜像,可以理解为代码控制中的代码仓库。Docker Hub提供了庞大的镜像集合供使用。
    Docker Machine Docker Machine是一个简化Docker安装的命令行工具,通过一个简单的命令行即可在相应的平台上安装Docker,比如VirtualBox、Digital Ocean、Microsoft Azure

    1.2 Docker改变了什么?

    • 面向产品:产品交付
    • 面向开发:简化环境配置
    • 面向测试:多版本测试
    • 面向运维:环境一致性
    • 面向架构:自动化扩容(微服务)

    2. 安装Docker

    安装Docker请查另一篇博客:https://www.jianshu.com/p/87e7f6ada205

    启动docker

    $ sudo systemctl start docker
    

    3. Docker镜像

    3.1 Docker拉取镜像加速

    需要先登录DaoCloud网站http://www.daocloud.io/mirror

    image.png

    点击立即使用,然后登录,然后选择你的系统:


    image.png

    Linux执行如下命令。

    [root@linux-host2 ~]# curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://4a1df5ef.m.daocloud.io
    docker version >= 1.12
    {"registry-mirrors": ["http://4a1df5ef.m.daocloud.io"]}
    Success.
    
    

    这条命令实际上是在/etc/docker/daemon.json文件中加一行配置:

    {"registry-mirrors": ["http://4a1df5ef.m.daocloud.io"]}
    

    3.2 镜像相关的命令

    docker search <镜像名关键字>      # 搜索镜像
    docker pull <镜像名称>          # 拉取镜像
    docker images                   # 列出本地镜像
    docker rmi <镜像名称>           # 删除镜像
    

    3.3 导出/导入镜像

    # 先查看已有的镜像
    [root@linux-host2 ~]# docker images
    REPOSITORY                    TAG                 IMAGE ID            CREATED             SIZE
    hub.c.163.com/public/centos   7.2                 2ce04a284fa8        21 months ago       288 MB
    docker.io/training/webapp     latest              6fae60ef3446        2 years ago         349 MB
    
    
    # 导出镜像
    # docker save hub.c.163.com/public/centos:7.2 > centos-7.2.tar.gz
    
    
    # 导入镜像
    # docker load < /root/centos-7.2.tar.gz
    

    4. Docker应用

    使用docker run命令来在容器内运行一个应用程序,输出Hello World

    [root@openstack-control2 ~]# docker run ubuntu:15.10 /bin/echo "Hello world"
    

    参数解析:

    • run:运行一个容器;
    • ubuntu:15.10:指定要运行的镜像,Docker首先从本地主机上查找镜像是否存在,如果不存在,Docker就会从镜像仓库Docker Hub下载公共镜像;
    • /bin/echo "Hello World":在启动的容器里执行的命令。

    以上命令完整的意思可以解释为:Docker 以 ubuntu15.10 镜像创建一个新容器,然后在容器里执行 bin/echo "Hello world",然后输出结果。

    Centos7 的Docker 镜像地址修改

    4.1 运行容器

    4.1.1 运行交互式的容器
    [root@openstack-control2 docker]# docker run -i -t ubuntu:15.10 /bin/bash
    

    参数解析:

    • -i:允许你对容器的标准输入(STDIN)进行交互;
    • -t:在新容器内指定一个伪终端或终端。
    4.1.2 启动容器(后台模式)
    [root@openstack-control2 docker]# docker run -d ubuntu:15.10 /bin/sh -c "while true;do echo hello-world;sleep 1;done"
    02c285ff03bbf167796be5e1b4ce7b2a835d8d795e68b4375e1ec61b892ed42b
    

    参数解析:

    • -d:后台模式运行docker容器;
    • 还可以用--name xxx指定容器名称叫xxx。
    • 还可以用--rm,当容器停止运行后自动删除,一般用在测试时。
    • --restart always: 如果加上此选项,表示这个容器会在docker进程启动后,立即自己启动。

    那一长串字符串是容器ID,对每个容器来说是唯一的;

    4.2 --entrypoint的作用

    有些容器启动后会直接在前台运行命令,导致你进入容器后不能做其他的事情。这时你可以使用run命令下的参数--entrypoint,它的作用是覆盖镜像的默认入口点,示例如下:

    启动一个以python3.6为基础镜像的容器:

    [root@docker ~]# docker run -it --name python3.6 python:3.6
    Python 3.6.5 (default, Mar 31 2018, 01:15:58) 
    [GCC 4.9.2] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> 
    >>> 
    >>>
    

    容器启动后,直接进入python的交互终端了,不能做其它操作,而exit后,就直接退出容器了。这里加入--entrypoint bash参数,用bash覆盖它默认的入口点。

    [root@docker ~]# docker run -it --entrypoint /bin/bash --name python3.6 python:3.6
    root@430e3c9c09ac:/# 
    root@430e3c9c09ac:/# 
    

    这样进入容器后,就是bash交互了。

    4.3 列出容器

    列出正在运行的容器

    [root@openstack-control2 docker]# docker ps
    

    注意:默认只显示正在运行的容器,加 -a(或 --all)参数,可以显示出所有容器。
    **-l **:查询最后一次创建的容器

    列出所有容器

    [root@openstack-control2 docker]# docker ps -a
    CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                        PORTS               NAMES
    02c285ff03bb        ubuntu:15.10        "/bin/sh -c 'while..."   12 minutes ago      Exited (137) 11 minutes ago                       practical_hopper
    7f1ee35531a8        ubuntu:15.10        "/bin/bash"              19 minutes ago      Exited (0) 18 minutes ago                         upbeat_wiles
    

    解释:

    • CONTAINER ID:容器ID,可以通过容器ID来操作此容器,也可以用容器名称;
    • IMAGE:此容器是由哪个镜像创建的;
    • COMMAND:容器中运行的命令;
    • CREATED:创建时间;
    • STATUS:容器状态,Exited表示退出;
    • NAMES:是启动容器时,随机为容器分配的一个名称,也可以用来操作容器。

    查看所有容器的ID

    $ docker ps -a -q    # 这条命令会将所有容器的ID显示(只显示容器ID)
    

    4.4 查看容器内的标准输出

    [root@openstack-control2 docker]# docker logs 2b1b7a428627
    

    可以用容器ID或容器名称(用docker ps查看)

    4.5 停止容器

    [root@openstack-control2 docker]# docker stop 7f1ee35531a8
    

    4.6 杀死正在运行的容器

    [root@linux-host2 ~]# docker kill 000ed90ec053
    

    4.7 查看容器对硬件资源的占用情况

    [root@openstack-control2 docker]# docker stats 7f1ee35531a8
    

    如果不指定容器ID或名称,则默认显示所有正在运行的容器的资源占用情况;加 -a(或--all),则显示所有的容器;

    4.8 查看容器的进程

    [root@linux-host2 ~]# docker top adoring_noether
    UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
    root                9127                9115                0                   00:05               ?                   00:00:00            python app.p
    

    4.9 查看容器的配置和状态信息

    [root@linux-host2 ~]# docker inspect adoring_noether
    [
        {
            "Id": "251a6cacd10d5117025bda929ec1fb12f18b49cd2596c54d626c0c0e99491f48",
            "Created": "2018-04-13T16:05:01.028216802Z",
            "Path": "python",
            "Args": [
                "app.py"
            ],
            "State": {
                "Status": "running",
                "Running": true,
                "Paused": false,
                "Restarting": false,
                "OOMKilled": false,
                "Dead": false,
                "Pid": 9127,
                "ExitCode": 0,
                "Error": "",
                "StartedAt": "2018-04-13T16:05:01.186294688Z",
                "FinishedAt": "0001-01-01T00:00:00Z"
            },
    省略...
    

    可以通过--format参数查看容器的指定参数

    # 查看容器的状态
    [root@linux-host2 ~]# docker inspect --format '{{.State.Status}}' mycentos-2
    running
    
    # 查看容器的PID
    [root@linux-host2 ~]# docker inspect --format '{{.State.Pid}}' mycentos-2
    36897
    

    点击查看官方inspect数据获取的方法

    4.10 进入容器

    方式一:

    # docker attach mycentos-2   # 进入名为mycentos-2的容器
    

    这种方式进入容器容易卡死,而且exit退出后,容器也随即停止,如果想让容器在后台运行,可以用快捷键 Ctrl+p+q

    方式二:

    # docker exec -it 容器ID /bin/bash
    

    直接exit退出容器而不会中断容器运行。

    方式三:

    先获取容器的PID

    [root@linux-host2 ~]# docker inspect --format '{{.State.Pid}}' mycentos-2
    36897
    

    然后利用nsenter命令进入到容器中

    [root@linux-host2 ~]# nsenter -t 36897 -u -i -n -p
    [root@000ed90ec053 ~]#
    

    这样即使退出容器了,容器也不会停止运行。nsenter命令可以进入到指定PID进程的名称空间。如果系统没有nsenter命令,则需要安装yum install util-linux

    写成脚本,更方便:

    [root@linux-host2 ~]# cat in_container.sh 
    #!/bin/bash
    CID=$1
    PID=$(docker inspect --format "{{.State.Pid}}" $CID) 
    nsenter -t $PID -u -i -n -p
    

    调用:

    # ./in_container.sh mycentos-2
    

    4.11 查看WEB应用程序日志

    [root@linux-host2 ~]# docker logs -f 251a6cacd10
     * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
    192.168.10.1 - - [13/Apr/2018 16:05:10] "GET / HTTP/1.1" 200 -
    192.168.10.1 - - [13/Apr/2018 16:07:45] "GET / HTTP/1.1" 200 -
    

    -f:让容器中运行的web日志像使用tail -f一样来输出容器内部的标准输出。

    4.12 移除容器

    # 需要先停止容器
    [root@linux-host2 ~]# docker stop adoring_noether
    
    # 然后再删除指定的容器
    [root@linux-host2 ~]# docker rm adoring_noether
    

    4.13 导出容器

    [root@linux-host6 ~]# docker export -o mytomcat.tar mytomcat
    
    • mytomcat.tar是将容器导出后保存为mytomcat.tar文件名;
    • mytomcat是容器名称,这里也可以写容器ID。

    5. 端口映射

    5.1 用-P随机端口映射

    # 拉取镜像
    [root@openstack-control2 docker]# docker pull training/webapp
    
    # 运行容器
    [root@openstack-control2 docker]# docker run -d -P training/webapp python app.py
    80f795a76ac1ef52b8f3a47cca2ae670cdbcd6fc42d01e702fbdbd53d6a41f51
    

    -d:让容器在后台运行;
    -P:将容器内部使用的端口映射宿主机上一个随机端口。

    通过docker ps查看正在运行的容器:

    image.png

    多了端口信息:

    PORTS
    0.0.0.0:32768->5000/tcp
    

    左边是宿主机端口,右边是容器内开启的端口;就是做了一个端口映射;

    5.2 用-p来指定端口映射

    [root@linux-host2 ~]# docker run -d -p 8000:5000 training/webapp python app.py
    5959c85fae98e363cf2d339847fd3039f0de4b107fed2b362e905f74f176e55a
    [root@linux-host2 ~]# 
    [root@linux-host2 ~]# 
    [root@linux-host2 ~]# docker ps
    CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                    NAMES
    5959c85fae98        training/webapp     "python app.py"     5 seconds ago       Up 4 seconds        0.0.0.0:8000->5000/tcp   pensive_payne
    

    指定IP:PORT映射

    [root@linux-host2 ~]# docker run -d --name myweb -p 192.168.10.202:8000:5000 training/webapp python app.py
    bf73ccb767a52a1f14a2c11a913a0d7d77263edc612380514e3ec0de489bb46f
    
    PORTS
    192.168.10.202:8000->5000/tcp
    

    5.3 查看容器端口的映射情况

    [root@linux-host2 ~]# docker port 251a6cacd10d
    5000/tcp -> 0.0.0.0:8000
    

    6. Docker数据管理

    6.1 数据卷

    将宿主机下的某个目录挂载至指定的容器目录。

    如果不指定将哪个宿主机目录挂载至容器目录,则默认会将/var/lib/docker/vloumes/容器ID/_data挂载至容器。

    # docker run -it --name centos7.2 -v /data public/centos:7.2 /bin/bash
    

    直接使用-v /data会将宿主机的某个目录挂载至容器的/data目录。
    这个目录可以通过下面这条命令查看到;

    [root@linux-host2 ~]# docker inspect --format "{{(index .Mounts 0).Source}}" centos7.2
    /var/lib/docker/volumes/2a97b4ef3be22d590edf90089ee9fb32cf5a5848faa15076fff8f522bcbf406d/_data
    

    指定宿主机目录挂载至容器

    # docker run -it --name test1 -v /opt/data/:/data:ro public/centos:7.2 /bin/bash
    

    -v src:dst:ro , src 是主机目录,dst是容器目录,ro是只读权限。

    6.2 数据卷容器

    数据卷容器就是专门启动一个容器挂载一个目录,以后其他的容器直接从数据卷容器来挂载目录,即使数据卷容器停止了,也不影响这些容器访问挂载的目录。使用--volumes-from

    # 先启动一个容器test1用来提供数卷
    $ docker run -it --rm --name test1 -v /data public/centos:7.2 /bin/bash
    
    
    # 再启动一个容器test2,从test1容器挂载/data目录至test2的/data目录。 
    $ docker run -it --name test2 --volumes-from test1 public/centos:7.2 /bin/bash
    

    7. 手动构建一个镜像

    我们以构建一个Nginx容器为例。

    7.1 先拉取一个基础镜像

    $ docker pull centos
    

    7.2 利用基础镜像启动一个容器

    $ docker run -it --name mynginx public/centos /bin/bash
    

    7.3 在容器内安装nginx,并修改配置为使nginx为前台运行

    $ yum -y install nginx
    
    $ echo "daemon off;" >> /etc/nginx/nginx.conf
    

    7.4 提交镜像

    $ docker commit -m "My nginx" mynginx oldboyedu/mynginx:v1  
    

    commit提交镜像至本地仓库,用docker images查看镜像是否生成。

    • 命令格式:docker commit -m "描述信息" CID new_image
      CID:是将要以哪个容器生成新的镜像的容器ID或名称;
      new_image:是新镜像的名称及版本,(镜像名称与版本号用冒号:分隔。)

    7.5 生成新容器

    $ docker run -d --name nginx -p 81:80 -v /wwwroot:/data oldboyedu/mynginx:v1 nginx
    

    最后跟着的nginx是nginx启动命令。

    8. Dockerfile构建镜像

    Dockerfile需要包含以下信息:

    • 基础镜像信息
    • 维护者信息
    • 镜像操作指令
    • 容器启动时执行的命令

    8.1 Dockerfile中的关键字指令

    Dockerfile通常包含以下关键字指令:

    • FROM:它的妈妈是谁(基础镜像
    • MAINTAINER:告诉别人,你创造了它(维护者信息
    • RUN:你想让它干啥(把shell命令前面加上RUN
    • ADD:往它肚子里放点文件(copy文件,会自动解压
    • WORKDIR:我是cd,今天化了妆(当前工作目录
    • VOLUME:给我一个存放行李的地方(目录挂载
    • EXPOSE:我要打开哪扇门(开启的端口
    • CMD:最后启动容器要执行的命令,如:CMD ["apachetcl -D FOREGROUND"]

    8.2 Dockerfile示例

    一个构建Nginx容器的Dockerfile示例:

    [root@linux-host2 data]# vim Dockerfile

    # This Dockerfile is build nginx container
    
    # 基础镜像
    FROM public/centos:7.2
    
    # 维护者
    MAINTAINER caigy caigy@163.com
    
    # 执行的操作
    RUN curl http://mirrors.aliyun.com/repo/epel-7.repo -o /etc/yum.repos.d/epel.repo 
    RUN yum install -y nginx
    
    # 添加文件至容器中
    ADD index.html /usr/share/nginx/html/index.html
    
    # 修改nginx配置文件
    RUN echo "daemon off;" >> /etc/nginx/nginx.conf
    
    # 开启端口
    EXPOSE 80
    
    # 启动容器时要执行的命令
    CMD ["nginx"]
    

    开始构建:

    $ docker build -t caigy/nginx:1.0 /opt/data/

    注意:基于Dockerfile构建镜像时,需要指定Dockerfile父目录(上述命令中的/opt/data/),或者用.指代当前目录,表示Dockerfile就在当前目录下。

    • -t :为镜像打一个标签。

    以下是构建过程中的输出:

    Sending build context to Docker daemon 6.144 kB
    Step 1/8 : FROM public/centos:7.2
     ---> 2ce04a284fa8
    Step 2/8 : MAINTAINER caigy caigy@163.com
     ---> Using cache
     ---> b7e06003d244
    Step 3/8 : RUN curl http://mirrors.aliyun.com/repo/epel-7.repo -o /etc/yum.repos.d/epel.repo
     ---> Running in 31b2f1dafe05
    
      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
    100  1084  100  1084    0     0  14137      0 --:--:-- --:--:-- --:--:-- 14263
     ---> c4b667b90187
    Removing intermediate container 31b2f1dafe05
    Step 4/8 : RUN yum install -y nginx
     ---> Running in 10ec5f05491e
    
    省略部分输出......
    
    Step 7/8 : EXPOSE 80
     ---> Running in 027863d66b45
     ---> 8cc1cdc2c890
    Removing intermediate container 027863d66b45
    Step 8/8 : CMD nginx
     ---> Running in 9d62c62bd97c
     ---> 2f8bea7e3937
    Removing intermediate container 9d62c62bd97c
    Successfully built 2f8bea7e3937
    

    查看本地镜像是否有刚才构建的镜像:

    [root@linux-host2 data]# docker images
    REPOSITORY                    TAG                 IMAGE ID            CREATED             SIZE
    caigy/nginx                   1.0                 2f8bea7e3937        7 minutes ago       477 MB
    

    8.3 启动容器

    利用刚刚构建的镜像启动一个容器:

    [root@linux-host2 data]# docker run -d --name mynginx -p 8800:80 caigy/nginx:1.0 nginx
    e799d2abe242657477d356378981c801d0c5b49115a7b82965148d082fdbb74f
    

    查看容器:

    [root@linux-host2 data]# docker ps
    CONTAINER ID        IMAGE                  COMMAND                  CREATED             STATUS              PORTS                          NAMES
    e799d2abe242        caigy/nginx:1.0        "nginx"                  4 seconds ago       Up 4 seconds        22/tcp, 0.0.0.0:8800->80/tcp   mynginx
    

    假设宿主机ip是:x.x.x.x,那么浏览器输入:http://x.x.x.x:8800验证容器是否启动成功。

    9. CentOS 7.x 下Docker桥接网络配置

    docker默认提供了一个隔离的内网环境,启动时会建立一个docker0的虚拟网卡,每个容器都是连接到docker0网卡上的。而docker0的ip段为172.17.0.1,如果想让容器与宿主机同一网段的其他机器访问,就必须在启动docker的时候将某个端口映射到宿主机的端口。这样如果大家会发现很麻烦,而且在企业里面也没这么使用的,比较弱。

    大家应该知道KVM的桥接网络非常方便,其实docker也比较方便,至少不是自带的桥接而已,接下来讲解centos7下如何快速实现docker容器桥接网络,并为容器分配外网IP。

    物理机的IP:192.168.1.7 网关:192.168.1.1

    1. 停止docker服务;
      systemctl stop docker

    2. 新建桥接网卡br0;
      brctl addbr br0
      ip link set dev br0 up

    3. 为br0分配物理网络中的IP地址;
      这里可直接用宿主机的IP,接下来会清空宿主机的IP。
      ip addr add 192.168.1.7/24 dev br0

    4. 将宿主机网卡的IP清空,并将宿主机网卡挂至br0上;
      ip addr del 192.168.1.7/24 dev eth0
      brctl addif br0 eth0 # 将宿主机eth0网卡挂到br0上

    5. 删除原路由,并为br0设置路由
      ip route del default
      ip route add default via 192.168.1.1 dev br0

    6. 设置docker服务启动参数
      vim /etc/sysconfig/docker-network,其他系统可能在/etc/sysconfig/docker下。
      改成如下行即可:

      DOCKER_NETWORK_OPTIONS="-b=br0"
      
    1. 启动docker服务
      systemctl docker start

    2. 删除docker0网卡

      $ ip link set dev docker0 down  #先关闭docker0网卡
      $ brctl delbr docker0           #再删除
      
    3. 安装pipework
      git clone https://github.com/jpetazzo/pipework
      cp ./pipework/pipework /usr/local/bin/

    4. 启动容器并设置网络
      docker run -itd --net=none --name=mycentos cgy/mycentos:v1 /bin/bash

    5. 为mycentos容器设置一个与桥接物理网络同地址段的 ip/掩码@网关
      pipework br0 mycentos 192.168.1.10/24@192.168.1.1

    6. 进入容器查看IP
      docker exec -it mycentos /bin/bash
      如下图:

      image.png

    以上2~5步通过命令行新建的桥接网卡br0,在服务器重启后就会失效,要想永久生效,就需要创建网卡配置文件了。如下 :

    1. 新建br0的网卡配置文件;
      vim /etc/sysconfig/network-scripts/ifcfg-br0
    TYPE=Bridge
    DEVICE=br0
    ONBOOT=yes
    BOOTPROTO=static
    IPADDR=192.168.1.7
    GATEWAY=192.168.1.1
    PREFIX=24
    NM_CONTROLLED=no
    DNS1=8.8.8.8
    
    1. 修改eth0网卡配置文件:
      vim /etc/sysconfig/network-scripts/ifcfg-eth0
    TYPE="Ethernet"
    BOOTPROTO="static"
    NAME="eth0"
    UUID="5c013315-95d6-4f08-a61d-1b8340a9cb94"
    DEVICE="eth0"
    ONBOOT="yes"
    BRIDGE=br0      # 表示桥接至br0网卡上
    
    1. 重启网卡
      systemctl restart network

    10. Docker磁盘热扩容

    默认情况下,docker容器的空间是10G。在实际生产环境下,对docker容器进行热扩容(动态扩容)是非常重要的一个需求。

    Docker容器动态扩展的优点:
    1)不需要修改docker配置,不需要重启docker服务;
    2)可以直接对运行中的容器进行动态扩展(只能增,无法缩);

    Docker容器动态扩展的条件:
    1)docker存储引擎必须是devicemapper。可通过docker info查看:Storage Driver: devicemapper

    10.1 操作环境

    宿主机系统版本:

    [root@linux-host2 ~]# cat /etc/redhat-release 
    CentOS Linux release 7.2.1511 (Core)
    

    Docker版本:

    [root@linux-host2 ~]# docker version
    Client:
     Version:   18.04.0-ce
     API version:   1.37
     Go version:    go1.9.4
     Git commit:    3d479c0
     Built: Tue Apr 10 18:21:36 2018
     OS/Arch:   linux/amd64
     Experimental:  false
     Orchestrator:  swarm
    
    Server:
     Engine:
      Version:  18.04.0-ce
      API version:  1.37 (minimum version 1.12)
      Go version:   go1.9.4
      Git commit:   3d479c0
      Built:    Tue Apr 10 18:25:25 2018
      OS/Arch:  linux/amd64
      Experimental: false
    

    10.2 启动一个容器

    # 启动容器
    [root@linux-host2 ~]# docker run -itd --name mycentos cgy/mycentos:v1 /bin/bash
    56b03239e57c99802bba279d20f1437621269b74eb15d8d6a712c3f56f740541
    
    # 进入容器查看分区大小
    [root@linux-host2 ~]# docker attach mycentos
    [root@ebec89c0ee40 /]# df -HT
    Filesystem                                                                                        Type   Size  Used Avail Use% Mounted on
    /dev/mapper/docker-253:0-67921092-b65077731c946204e67b376e591d0e6290a5c4572ee2568c275b4afbf5b32486 xfs     10G  375M   9.7G   4% /
    tmpfs                                                                                             tmpfs   68M     0   68M   0% /dev
    tmpfs                                                                                             tmpfs  2.0G     0  2.0G   0% /sys/fs/cgroup
    /dev/mapper/docker-root                                                                           ext4    32G  462M   29G   2% /etc/hosts
    shm                                                                                               tmpfs   68M     0   68M   0% /dev/shm
    tmpfs                                                                                             tmpfs  2.0G     0  2.0G   0% /proc/scsi
    tmpfs                                                                                             tmpfs  2.0G     0  2.0G   0% /sys/firmware
    

    使用ctrl+p+q退出容器而不使其中断。

    注意:容器mycentos的磁盘空间默认为10G左右,/dev/mapper/docker-253:0-67921092-b65077731c946204e67b376e591d0e6290a5c4572ee2568c275b4afbf5b32486就是容器mycentos的存储设备文件名。

    接下来就开始进行容器存储空间的动态扩容

    10.3 开始容器存储空间动态扩容

    使用dmsetup查看该文件扇区信息.下面命令结果中的第二个数字(即20971520)是设备的大小,表示有20971520个 512-bytes 的扇区. 这个值(20971520*512bytes)略高于 10GB 的大小。

    [root@linux-host2 ~]# dmsetup table /dev/mapper/docker-253:0-67921092-b65077731c946204e67b376e591d0e6290a5c4572ee2568c275b4afbf5b32486
    0 20971520 thin 253:2 9
    

    计算20G所需扇区数目

    [root@linux-host2 ~]# echo $((20*1024*1024*1024/512))
    41943040
    

    将新的扇区大小写入,注意只是改变旧表中的第二个数字20971520的数字,其他数字不变!

    [root@linux-host2 ~]# echo 0 41943040 thin 253:2 9 | dmsetup load /dev/mapper/docker-253:0-67921092-b65077731c946204e67b376e591d0e6290a5c4572ee2568c275b4afbf5b32486
    

    将修改后的容器存储文件激活

    [root@linux-host2 ~]# dmsetup resume /dev/mapper/docker-253:0-67921092-b65077731c946204e67b376e591d0e6290a5c4572ee2568c275b4afbf5b32486
    

    重新查看文件信息

    [root@linux-host2 ~]# dmsetup table /dev/mapper/docker-253:0-67921092-b65077731c946204e67b376e591d0e6290a5c4572ee2568c275b4afbf5b32486
    0 41943040 thin 253:2 9
    

    更改文件系统大小,使变更生。

    [root@linux-host2 ~]# xfs_growfs /dev/mapper/docker-253:0-67921092-b65077731c946204e67b376e591d0e6290a5c4572ee2568c275b4afbf5b32486
    meta-data=/dev/mapper/docker-253:0-67921092-b65077731c946204e67b376e591d0e6290a5c4572ee2568c275b4afbf5b32486 isize=256    agcount=16, agsize=163824 blks
             =                       sectsz=512   attr=2, projid32bit=1
             =                       crc=0        finobt=0
    data     =                       bsize=4096   blocks=2621184, imaxpct=25
             =                       sunit=16     swidth=16 blks
    naming   =version 2              bsize=4096   ascii-ci=0 ftype=0
    log      =internal               bsize=4096   blocks=2560, version=2
             =                       sectsz=512   sunit=16 blks, lazy-count=1
    realtime =none                   extsz=4096   blocks=0, rtextents=0
    data blocks changed from 2621184 to 5242880
    

    如果文件系统是ext2、ext3、ext4格式的,则要用resize2fs <设备文件>命令,使之变更。

    如果是xfs文件系统,用resize2fs命令去操作则会报如下错误:

    [root@linux-host2 ~]# resize2fs /dev/mapper/docker-253:0-67921092-b65077731c946204e67b376e591d0e6290a5c4572ee2568c275b4afbf5b32486
    resize2fs 1.42.9 (28-Dec-2013)
    resize2fs: Bad magic number in super-block while trying to open /dev/mapper/docker-253:0-67921092-b65077731c946204e67b376e591d0e6290a5c4572ee2568c275b4afbf5b32486
    Couldn't find valid filesystem superblock.
    

    再次登录mycentos容器,发现容器大小已经更新为20G左右!

    [root@linux-host2 ~]# docker attach mycentos
    [root@56b03239e57c /]# 
    [root@56b03239e57c /]# 
    [root@56b03239e57c /]# df -HT
    Filesystem                                                                                         Type   Size  Used Avail Use% Mounted on
    /dev/mapper/docker-253:0-67921092-b65077731c946204e67b376e591d0e6290a5c4572ee2568c275b4afbf5b32486 xfs     22G  394M   22G   2% /
    tmpfs                                                                                              tmpfs   68M     0   68M   0% /dev
    tmpfs                                                                                              tmpfs  2.0G     0  2.0G   0% /sys/fs/cgroup
    /dev/mapper/centos-root                                                                            xfs     54G  5.2G   48G  10% /etc/hosts
    shm                                                                                                tmpfs   68M     0   68M   0% /dev/shm
    tmpfs                                                                                              tmpfs  2.0G     0  2.0G   0% /proc/scsi
    tmpfs                                                                                              tmpfs  2.0G     0  2.0G   0% /sys/firmware
    

    扩容后可能出现的问题:停止该容器后,无法重新启动-
    当容器扩容之后,由于dm认为设备块大小仍然为之前设置的初始大小,所以会发生无法起启动的情况,这时只要重新操作即可。

    1)必须要先启动一下,让其生成dm文件才能修改
    [root@linux-host2 ~]# docker start mycentos
        //此时报错不必理会,执行以下操作即可
    
    [root@linux-host2 ~]# echo 0 41943040 thin 253:2 9 | dmsetup load /dev/mapper/docker-253:0-67921092-b65077731c946204e67b376e591d0e6290a5c4572ee2568c275b4afbf5b32486
    [root@linux-host2 ~]# 
    [root@linux-host2 ~]# dmsetup resume /dev/mapper/docker-253:0-67921092-b65077731c946204e67b376e591d0e6290a5c4572ee2568c275b4afbf5b32486
    [root@linux-host2 ~]# 
    [root@linux-host2 ~]# docker start mycentos
    mycentos
    

    为了方便后续容器动态扩容,可以采用下面的Dynamic_Modify_Docker_Disk.sh脚本(经测试可以使用)

    #!/usr/bin/env bash
    # This script is dynamic modify docker container disk
    # Author Deng Lei
    # 参数:
    #       $1 : 容器名称或容器ID
    #       $2 : 扩容后的大小,默认单位是GB,只写数字即可
    
    
    if [ -z $1 ] || [ -z $2 ]; then
        echo "Usage: container_name increase_capacity"
        echo "\tsh `basename $0` <container_name> <size>"
        echo "Example: I want increase 11G to test"
        echo "The command is:   sh `basename $0` test 11"
        exit 1
                                                                                                                                                            fi
    if [ `docker inspect $1 &>>/dev/null &&  echo 0 || echo 1` -eq 1 ];then
        echo "ERROR: The container $1 is no exist!"
        exit 1
    fi
    
    # 如果$2输入的不是纯数字,例如:20G,则$?为0,可以以此判断$2输入的是否为纯数字
    echo $2 | grep [^0-9] &>/dev/null && echo "ERROR: Size is a Pure digital" && exit 1
    
    device_name=`docker inspect -f "{{.GraphDriver.Data.DeviceName}}" $1`
    device_file=/dev/mapper/$device_name
    
    now_disk=`dmsetup table $device_file | awk '{print $2}'`
    disk=$(($2*1024*1024*1024/512))
    if [ $disk -lt $now_disk ];then
        echo "ERROR: I can't shink container $1 from $(($now_disk*512/1024/1024/1024))G to ${2}G!I only modify contanier increase disk!"
        exit 1
    fi
    dmsetup table $device_file | sed "s/0 [0-9]* thin/0 $disk thin/" | dmsetup load $device_file
    dmsetup resume $device_file
    
    # 如果是ext2|ext3|ext4 请将如下xfs_growfs命令替换成resize2fs命令
    xfs_growfs $device_file &>/dev/null
    
    if [ $? -eq 0 ];then
        echo -e "\033[1;32mDynamic expansion container $1 disk to ${2}G is success!\033[0m"
    else
        echo "Dynamic expansion container $1 disk to ${2}G is failed!"
    fi
    

    利用上述脚本给mycenos1容器动态扩容至25G

    [root@docker ~]# chmod 755 dynamic_expansion_docker_disk.sh
    [root@docker ~]# ./dynamic_expansion_docker_disk.sh mycentos1 25
    dynamic container mycentos1 disk to 25G is success!
    

    动态扩容后,对容器进行重启,会发生报错,此时再运行一次该脚本进行重新扩容(空间大小要等于或大于之前的设置,出现报错不用管),再启动容器即可(注意:docker容器目前是无法进行动态缩减的,仅能进行增加操作)。


    延伸:
    点击查看根分区扩展容量:LVM根分区扩容

    容器硬盘热扩容和Docker镜像和容器存放目录修改方法:https://www.cnblogs.com/kevingrace/p/6667063.html

    使用 Device Mapper来改变Docker 容器的大小:https://blog.csdn.net/feiskyer/article/details/41248123

    11. Docker仓库

    11.1 将本地镜像推送到公有仓库

    先查看一下本地的镜像:

    [root@linux-host2 ~]# docker images
    REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
    cgy/mycentos        v1                  32f504582f68        33 hours ago        347MB
    

    将本地cgy/mycentos:v1这个镜像打个标签

    [root@linux-host2 ~]# docker tag mycentos:1.0 cgy/mycentos:v1
    

    因为docker默认是将镜像推送到官方镜像仓库,所以你得先去hub.docker.com注册一个账号,然后再回来docker login登录,才能推送成功。

    [root@linux-host2 ~]# docker login
    Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
    Username: cgy0903        # 输入用户名
    Password:                # 输入密码
    

    推送镜像至公共仓库:

    [root@linux-host2 ~]# docker push mycentos:1.0
    

    11.2 搭建私有镜像仓库

    1. 先pull一下官方的registry镜像
    [root@linux-host2 ~]# docker pull registry
    
    1. 运行容器
    [root@linux-host2 ~]# docker run -d -p 5000:5000 --restart always --name registry registry:latest
    d8532caa38586f40769c0c0e0c30d26227329270648b6d51c9cb3df5a0443f38
    

    --restart always表示容器会在docker进程重启后,立即跟着自己启动,无须手动操作。

    1. 打标签
      Usage: docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
    [root@linux-host2 ~]# docker tag mycentos:1.0 localhost:5000/mycentos:1.0
    
    1. 推送镜像
    [root@linux-host2 ~]# docker push localhost:5000/mycentos:1.0
    The push refers to repository [localhost:5000/mycentos]
    907467dd33d7: Pushed 
    43e653f84b79: Pushed 
    1.0: digest: sha256:57ab246be805bb5758d09cbcf874e5e4f94550428c7f365195fc254aebc9afc4 size: 741
    

    速度快多了。

    注意:虽然自建的私有仓库速度快多了,但是还是感觉不好用,它没用友好的交互界面。这就需要用到harbor了。

    11.3 搭建harbor

    harbor是VMWare开源的一个存储和分发Docker镜像的企业级注册服务器,github地址:https://github.com/vmware/harbor 。Harbour提供更好的性能和安全性。此外,Harbor还提供高级安全功能,例如用户管理,访问控制和活动审计。

    1. 下载
    $ wget https://github.com/vmware/harbor/archive/v1.4.0.tar.gz
    
    1. 解压
    [root@docker src]# tar xvf harbor-offline-installer-v1.4.0.tgz
    
    # 进入安装目录下
    [root@docker src]# cd harbor
    
    1. 修改配置
    [root@docker harbor]# pwd
    /usr/src/harbor
    [root@docker harbor]# vim harbor.cfg
    hostname = 192.168.1.7      # 主机名或IP,不可以是localhost或127.0.0.1
    harbor_admin_password = Harbor12345     # web界面登录密码
    

    我们只配置上述两项即可,此外harbor.cfg中还有邮件发送、LDAP、以及数据库相关配置,根据需要再进行配置即可。

    1. 安装
    [root@docker harbor]# ./install.sh 
    
    [Step 0]: checking installation environment ...
    
    Note: docker version: 18.04.0
    ✖ Need to install docker-compose(1.7.1+) by yourself first and run this script again.
    

    报错:提示需要安装docker-compose 1.7.1以上版本。

    安装docker-compose 1.9

    [root@docker harbor]# yum list | grep docker-compose
    docker-compose.noarch                    1.9.0-5.el7                   epel     
    [root@docker harbor]# 
    [root@docker harbor]# yum install -y docker-compose
    

    再次安装

    [root@docker harbor]# ./install.sh
    
    [Step 0]: checking installation environment ...
    
    Note: docker version: 18.04.0
    
    Note: docker-compose version: 1.9.0
    
    [Step 1]: loading Harbor images ...
    ...
    ...
    ✔ ----Harbor has been installed and started successfully.----
    
    Now you should be able to visit the admin portal at http://hub.cgy.com. 
    For more details, please visit https://github.com/vmware/harbor .
    

    最后会提示安装成功并成功启动,
    访问htp://192.168.1.7

    harbor登录页面

    用户名:admin (默认),密码是harbor.cfg中harbor_admin_password配置的值。

    使用很简单,这里就不写教程了。

    相关文章

      网友评论

        本文标题:Docker入门

        本文链接:https://www.haomeiwen.com/subject/svgjkftx.html