Docker基础

Docker基础

介绍

解决了运行环境和配置问题软件容器,方便做持续集成并有助于整体发布的容器虚拟化技术

与传统虚拟化方式的不同

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

为什么比虚拟机快

  1. docker有比虚拟机更少的抽象层. 由于docker不需要Hypervisor实现硬件资源虚拟化,运行在docker容器上的程序直接使用的都是实际物理机的硬件资源. 因此在cpu,内存利用率上docker将会在效率上有明显优势
  2. docker利用的是宿主机的内核,而不需要GuestOS.
    1. 因此,当创建一个容器时,docker不需要和虚拟机一样重新加载一个操作系统内核. 创建一个虚拟机时,虚拟机软件需要加载GuestOS,整个新建过程是分钟级别的

三部分

  • 镜像 Image
  • 容器 Container
    • 容器是用镜像创建的运行实例
    • 每个容器都是相互隔离的
    • 可以把容器看作是一个简易版的Linux环境
  • 仓库 Repository
    • 集中存放镜像的地方
    • 分为公开仓库public和私有仓库private两种形式
      • 最大的公开仓库是Docker Hub. 国内有阿里云,网易云

安装

参考官网: https://docs.docker.com/engine/install/centos/

使用阿里云镜像加速

参考官网: https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors


常用命令

帮助命令

docker version

docker info

docker --help

镜像命令

docker images

  • -q 显示id
  • -a 列出全部

docker search

  • Options:

    • **–automated :**只列出 automated build类型的镜像;

    • **–no-trunc :**显示完整的镜像描述;

    • **-f <过滤条件>:**列出收藏数不小于指定值的镜像。(低版本是-s)

      • docker search -f stars=10 java
        
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34
        35
        36
        37
        38
        39
        40
        41
        42
        43
        44
        45
        46
        47
        48
        49
        50
        51
        52
        53
        54
        55
        56
        57
        58
        59
        60
        61
        62
        63
        64
        65
        66
        67
        68
        69
        70
        71
        72
        73
        74
        75
        76
        77
        78
        79
        80
        81
        82
        83
        84
        85
        86
        87
        88
        89
        90
        91
        92
        93
        94
        95
        96
        97
        98
        99
        100
        101
        102
        103
        104
        105
        106
        107
        108
        109
        110
        111
        112
        113
        114
        115
        116
        117
        118
        119
        120
        121
        122
        123
        124
        125
        126
        127
        128
        129
        130
        131
        132
        133
        134
        135
        136
        137
        138
        139
        140
        141
        142
        143
        144
        145
        146
        147
        148
        149
        150
        151
        152
        153
        154
        155
        156
        157
        158
        159
        160
        161
        162
        163
        164
        165
        166
        167
        168
        169
        170
        171
        172
        173
        174
        175
        176

        ```docker pull``` : 拉取镜像

        * 默认latest

        ```docker rmi```: 删除镜像

        * 默认latest
        * 删除单个: ```docker rmi -f hello-world```
        * 删除多个: ```docker rmi -f hello-world nginx```
        * 删除全部: ```docker rmi -f $(docker images -q)```

        ### 容器命令

        有镜像才能创建容器

        #### 新建并启动容器

        ```docker run [OPTIONS] IMAGE [COMMAND][ARG...]```

        常用选项

        1. --name: 指定名称
        2. -d: 后台运行容器,并返回容器ID,也即**启动守护式容器**
        3. **-i: 以交互模式运行容器,通常与-t同时使用**
        4. **-t: 为容器重新分配一个伪输入终端,通常与-i同时使用**
        5. -P: 随机端口映射
        6. -p: 指定端口映射,有以下格式
        1. ip:hostPort:containerPort
        2. ip::containerPort
        3. hostPort:containerPort
        4. containerPort

        #### 列出所有正在运行的容器

        ```docker ps [OPTIONS]```

        常用选项

        * -a: 列出所有正在运行的容器+历史上运行过的
        * -l: 显示最近创建的容器
        * ~~-n: 显示最近n个创建的容器~~
        * -q: 静默模式,只显示容器编号
        * --no-trunc: 不截断输出

        #### 退出容器

        * exit: 容器停止退出
        * ctrl + P + Q: 容器不停止退出

        #### 启动容器

        * ```docker start CONTAINER ID/NAME```

        #### 重启容器

        * ```docker restart CONTAINER ID/NAME` ``

        #### 停止容器

        * ```docker stop CONTAINER ID/NAME```
        * 强制停止: ```docker kill CONTAINER ID/NAME```

        #### 删除已停止容器

        * ```docker rm CONTAINER ID```
        * 一次性删除多个容器
        * ```docker rm -f $(docker ps -a -q)```
        * ```docker ps -a -q | xargs docker rm```

        #### 守护进程启动

        * ```docker run -d CONTAINER NAME```
        * 使用```docker ps -a```查看,发现容器已经退出. 是因为**Docker容器后台运行,必须有一个前台进程**.
        * 容器运行的命令如果不是那些一直挂起的命令(比如top,tail),都是会自动退出
        * 这是docker的机制
        * **解决方案: 将要运行的程序用前台进程形式运行**

        #### 查看日志

        * ```docker logs -f -t --tail CONTAINER ID```
        * -t: 加入时间戳
        * -f: 跟随最新的日志打印
        * --tail 数字: 显示最后多少条

        #### 查看容器内运行的进程

        ```docker top CONTAINER ID```

        #### 查看容器内部细节

        ```docker inspect CONTAINER ID```

        #### 与容器以命令行交互

        * ```docker exec -it CONTAINER ID bashShell``` (推荐)
        * 可以进入容器(bashShell 写 /bin/bash)
        * 也可以在外面执行获取结果
        * ```docker attach CONTAINER ID```
        * 区别:
        * attach 是直接进入容器启动命令的终端,不会启动新的进程
        * exec 是在容器中打开新的终端,并且可以启动新的进程

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

        * ```docker cp CONTAINER ID:CONTAINER PATH HOSTPATH```

        ### 总结

        [Docker.mmap](../../../Downloads/Docker.mmap)

        ***

        ## 镜像

        * 镜像是一种轻量级的,可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件.
        * UnionFS(联合文件系统)
        * 是一种分层,轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加
        * 一次同时加载多个文件系统,但从外面看来,只能看到一个文件系统
        * docker镜像
        * bootfs (boot file system) 主要包含bootloader和kernl.
        * bootloader主要是引导加载kernel
        * Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs.
        * 这一层与典型的Linux系统是一样的,包含boot加载器和内核.当boot加载完成后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs
        * rootfs (root file system)
        * 在bootfs之上.
        * 包含就是Linux系统中的/dev,/proc,/bin,/etc等标准目录和文件.
        * rootfs就是各种不同的操作系统发行版,比如Ubuntu, CentOS
        * 好处:**共享资源**

        ### 操作

        #### commit

        ```docker commit```提交容器副本使之成为一个新的镜像

        ```docker commit -m="描述" -a="作者" 容器ID 要创建的目标镜像名:[标签名]```

        ***

        ## 容器数据卷

        * 持久化
        * 容器之间希望可以共享数据
        * docker里面的RDB,AOF

        ### 介绍

        * 卷就是目录或文件,存在于一个或多个容器中,由docker挂载到容器,但不属于联合文件系统,因此能够绕过Union File System提供一些用于持续存储或共享数据的特性
        * 设计目的就是数据持久化,完全独立于容器的生存周期,因此Docker不会在容器删除时删除其挂载的数据卷

        ### 特点

        1. 数据卷可用在容器之间共享或重用数据
        2. 卷中的更改可以直接生效
        3. 数据卷中的更改不会包含在镜像的更新中
        4. 数据卷的生命周期一直持续到没有容器使用它为止

        ### 添加

        #### 命令添加

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

        ```docker run -it -v /宿主机绝对路径目录:/容器内目录:ro 镜像名``` 容器内只读(ro:read only)

        #### dockerfile添加

        1. 编写

        ```dockerfile
        # volume test
        FROM centos
        VOLUME ["/dataVolumeContainer1","/dataVolumeContainer2"]
        CMD echo "finished,------success1"
        CMD /bin/bash
  1. 指定dockerfile 构建

    docker build -f /mydocker/DockerFile -t zyq/centos .

  2. 运行

    docker run -it zyq/centos

数据卷容器

介绍

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

命令

docker run -t --volumes-from CONTAINER NAME IMAGE

  • CONTAINER NAME: 继承自什么容器
  • IMAGE: 镜像名
  • 子与父之间共享数据卷!

结论

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


Dockerfile

简介

Dockerfile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本

构建三步骤

  1. 编写Dockerfile文件
  2. docker build
  3. docker run

构建过程解析

基础知识

  1. 每条保留字指令都必须为大写字母且后面要跟随至少一个参数
  2. 指令按照从上到下,顺序执行
  3. #表示注释
  4. 每条指令都会创建一个新的镜像层,并对镜像进行提交

执行流程

  1. docker从基础镜像运行一个容器
  2. 执行一条指令并对容器作出修改
  3. 执行类似docker commit的操作提交一个新的镜像层
  4. docker再基于刚提交的镜像运行一个新容器
  5. 执行dockerfile中的下一条指令直到所有指令都执行完成

总结

从应用软件的角度来看,Dockerfile,Docker镜像于Docker容器分别代表软件的三个不同阶段

  • Dockerfile是软件的原材料
  • Docker镜像是软件的交付品
  • Docker容器则可以认为是软件的运行态

Dockerfile面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可,合力充当Docker体系的基石.

Dockerfile涉及的内容包括执行代码或文件,环境变量,依赖包,运行时环境,动态链接库,操作系统的发行版,服务进程和内核进程等等

Dockerfile体系结构

FROM

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

MAINTAINER

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

RUN

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

EXPOSE

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

WORKDIR

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

ENV

  • 用来在构建镜像过程中设置环境变量

ADD

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

COPY

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

VOLUME

  • 容器数据卷,用于数据保存和持久化操作

CMD

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

ENTRYPOINT

  • 指定一个容器启动时要运行的命令
  • ENTRYPOINT的目的和CMD一样,都是在指定容器启动程序和参数
  • docker run之后的参数会被当作参数传递给ENTRYPOINT,之后形成新的命令组合

ONBUILD

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

案例

自定义镜像centos

目的
  1. 设置登录后的默认路径
  2. vim编辑器
  3. 查看网络配置ifconfig支持
步骤
  1. 编写文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    FROM centos
    MAINTAINER yiqing<y.zhang@live.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
  2. 构建 -f指定dockerfile文件

    docker build -t 新镜像名:TAG

    docker build -f /mydocker/dockerfile2 -t mycentos:1.3 .

  3. 运行

    docker run -it mycentos:1.3

自定义tomcat

  1. Dockerfile

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    FROM centos
    MAINTAINER yiqing<y.zhang@live.com>

    #把宿主机当前上下文的c.txt拷贝到容器/usr/local路径下
    COPY c.txt /usr/local/container.txt

    #把java与tomcat添加到容器中
    ADD jdk-8u281-linux-x64.tar.gz /usr/local/
    ADD apache-tomcat-10.0.2.tar.gz /usr/local/

    #安装vim
    RUN yum -y install vim

    #设置访问的落脚点
    ENV MYPATH /usr/local
    WORKDIR $MYPATH

    #配置java与tomcat环境变量
    ENV JAVA_HOME /usr/local/jdk1.8.0_281
    ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
    ENV CATALINA_HOME /usr/local/apache-tomcat-10.0.2
    ENV CATALINA_BASE /usr/local/apache-tomcat-10.0.2
    ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin

    #容器运行时监听的端口
    EXPOSE 8080

    #启动时运行tomcat
    CMD /usr/local/apache-tomcat-10.0.2/bin/startup.sh && tail -F /usr/local/apache-tomcat-10.0.2/bin/logs/catalina.out
  2. 构建

    统一目录下如果名字为Dockerfile,自动去找

    docker build -t yiqingtomcat10

  3. 运行

    1
    2
    3
    4
    5
    docker run -d -p 9080:8080 --name mytomcat10 \
    -v /mydockerfile/tomcat/test:/usr/local/apache-tomcat-10.0.2/webapps/test \
    -v /mydockerfile/tomcat/tomcat10logs/:/usr/local/apache-tomcat-10.0.2/logs \
    --privileged=true \
    yiqingtomcat10

安装服务

Mysql

  1. docker pull mysql

  2. 运行

    1
    2
    3
    4
    5
    6
    docker run -p 3306:3306 --name mysql \
    -v /mydockerfile/mysql/conf:/etc/mysql/conf.d \
    -v /mydockerfile/mysql/logs:/logs \
    -v /mydockerfile/mysql/data:/var/lib/mysql \
    -e MYSQL_ROOT_PASSWORD=123456 \
    -d mysql
  3. 交互

    docker exec -it mysql /bin/bash

  4. 登录mysql

    mysql -uroot -p

  5. 备份mysql

    docker exec mysql sh -c 'exec mysqldump --all-databases -uroot -p "123456"' > /yiqing/all-databases.sql

Redis

  1. docker pull redis

  2. docker run -p 6379:6379 --name redis \
    -v /mydockerfile/redis/data:/data \
    -v /mydockerfile/redis/conf/redis.conf:/usr/local/etc/redis/redis.conf \
    -d redis redis-server /usr/local/etc/redis/redis.conf \
    --appendonly yes
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25

    3. 创建redis.conf文件(略)

    4. 连接: ```docker exec -it redis redis-cli```

    ## 上传镜像到阿里云

    ### 从容器创建一个新的镜像

    ```docker commit [OPTIONS] CONTAINER ID [REPOSITORY[:TAG]]```

    示例: ```docker commit -a yiqing -m "new centos with vim and ifconfig" c8855ee794d3 mycentos:1.4```

    ### 推送到阿里云

    1. 登录阿里云容器镜像服务

    2. 创建镜像仓库

    3. 推送

    ```bash
    sudo docker login --username=[xxx] registry.cn-shanghai.aliyuncs.com
    sudo docker tag [ImageId] registry.cn-shanghai.aliyuncs.com/yiqing/personal:[镜像版本号]
    sudo docker push registry.cn-shanghai.aliyuncs.com/yiqing/personal:[镜像版本号]