跳转至

docker

Docker 基础知识

https://www.docker.com/
https://www.docker.org.cn/
https://www.bilibili.com/video/BV1Vs411E7AR?from=search&seid=7596747318335787395

开发 =》 运维:系统&环境&配置不一致,导致软件不能按预期运行

Docker: 代码/配置/系统/数据/... 整体环境打包  =》 软件带环境部署,避免在开发机器上正常工作,一部署到服务器上就各种问题


image: 

在集群部署场景中,会包含很多机器,在一台机器上装完环境后,需要一遍又一遍重复安装到其它机器,过程繁琐,但如果把其中一台机器的环境做成镜像,在分发到其它所有机器中,这样就很好地解决了集群部署过程中的繁琐过程

一次封装(构建),处处运行

docker三要素:仓库、镜像、容器


虚拟机:占用资源多、冗余步骤多、启动慢


LXC: Linux Containers


容器 =》 集装箱:没有自己的内核,没有硬件虚拟,彼此隔离
鲸鱼 =》 Docker


devops => 开发自运维


轻量:centos/ubuntu 基础镜像仅170M,仅包含业务运行时所需的runtime
高效:无操作系统虚拟化开销
敏捷,灵活
秒级启动


凡技术,必登官网


docker hub:镜像仓库 => github


lsb_release -a          
    No LSB modules are available.
    Distributor ID: Ubuntu
    Description:    Ubuntu 20.04 LTS
    Release:        20.04
    Codename:       focal


docker build
docker pull 
docker run

镜像:只读模板 =》 一个镜像可以创建多个容器
容器:镜像的实例  
    =》 Persion p1 = new Persion()
    =》 Persion p2 = new Persion()
    =》 Persion p3 = new Persion()

    Persion =》 镜像;p1,p2,p3 => 容器

    容器可以被启动、开始、停止、删除,每个容器相互隔离,每个容器就是一个集装箱,可以把容器看作是一个简易版的Linux环境(Linux很多命令可以在docker内使用)


仓库:集中存放镜像的场所


tag: 版本号


docker本身是一个容器运行载体或称之为管理引擎。我们把应用程序和配置依赖打包成一个可交付的运行环境,这个打包好的运行环境就是镜像文件(image),只有通过这个镜像文件才能生成docker容器,image文件可以看作是容器的模板。
docker根据image文件生成容器的实例,同一个image文件,可以生成多个同时运行的实例。


一个容器运行一种服务(如 nginx/redis/mysql等)


centos 6.8:
yum install -y epel-release 
yum install -y docker-io
/etc/sysconfig/docker => 配置文件地址


service docker start
windows docker desktop 手动重启


https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors

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


ps -ef | grep docker


docker run hello-world   (hello-world 为官方测试镜像)

===============================================================================================

大海   - 宿主机
鲸鱼   - docker
集装箱 - 容器实例(来自image)


Docker 常用命令

docker images   => 列出本地镜像列表

    REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
    hello-world   latest    bf756fb1ae65   11 months ago   13.3kB

    REPOSITORY: 镜像仓库源
    TAG: 镜像的标签
    IMAGE ID: 镜像ID
    CREATED: 镜像创建时间
    SIZE: 镜像大小

    同一个仓库源可以有多个TAG,代表这个仓库源的不同版本,我们使用 REPOSITORY:TAG 来定义不同的镜像。如果不指定一个镜像的版本标签,默认使用 latest 标签。


docker version                    => 查看docker版本
docker info                       => docker 信息

docker --help  images             => 查看 images 命令帮助信息

docker images -a                  => a: all, 列出本地所有镜像(包括中间映像层,镜像是分层的千层饼)
docker images -q                  => 仅显示镜像ID
docker images -aq                 => 列出本地所有镜像的镜像ID
docker images --digests           => 显示镜像的摘要信息
docker images --no-trunc          => 不截取,显示完整的镜像信息
docker images nginx --digests     => 显示某具体镜像的摘要信息

docker search nginx                                             => 从 docker hub (https://hub.docker.com) 上搜索镜像(NOTE: 查询地址和下载地址不一致,查询是从https://hub.docker.com查询,下载是从我们配的镜像地址下载 )
docker search nginx --no-trunc                                  => 不截取,显示完整的镜像信息
docker search nginx --limit 3                                   => 限制查询结果的最大返回个数
docker search nginx --filter stars=3 --filter is-official=true  => 搜索stars大于等于3且来源为官方版本的nginx镜像

    ➜  ~ docker search tomcat           
        NAME                          DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
        tomcat                        Apache Tomcat is an open source implementati…   2894      [OK]       
        tomee                         Apache TomEE is an all-Apache Java EE certif…   85        [OK]       
        dordoka/tomcat                Ubuntu 14.04, Oracle JDK 8 and Tomcat 8 base…   55                   [OK]

        dordoka/tomcat => dordoka 为命名空间



docker pull nginx                                               => 下载 nginx 镜像(未指定tag时默认下载最新版本,默认追加 latest TAG)

docker rmi nginx                                                => remove image, 删除镜像
docker rmi nginx -f                                             => 强制删除镜像,忽略该镜像被容器引用的场景
docker rmi nginx hello-world -f                                 => 强制删除多个镜像
docker rmi $(docker images -aq) -f                              => 强制删除所有镜像


docker run
    => -i: 以交互模式运行容器,通常与 -t 同时使用
    => -t: 为容器重新分配一个伪输入终端,通常与 -i 同时使用
    => -d: 后台运行容器,并返回容器ID,也即启动守护式容器
        NOTE: docker容器后台运行必须要有一个前台进程(容器运行的命令如果不是那些一直挂起的命令如 top/tail,就是会自动退出的)
    -p: 主机端口:docker容器端口
    -P: 随机分配端口
    => 运行容器时若未指定容器名称则docker自动随机生成一个容器名称

    docker run -it nginx
    docker run -d nginx
    docker run -it ubuntu  <=> 等价于  docker run -it ubuntu /bin/bash  (默认以 /bin/bash 运行)
    docker run -it -p 8888:8080 tomcat  => 指定端口 => http://localhost:8888
    docker run -it -P tomcat            => 随机端口 => 0.0.0.0:32768->8080/tcp => http://localhost:32768

    docker run -it --env-file tests/haa/config/env/localenv 4ada7665647c /bin/bash  => 传递环境变量到容器


docker run --name hhbcreate hello-world

    NOTE: docker 命令顺序错误可能会导致以下异常产生,如下:
        (haa_test) ➜  haa-test git:(hhb) ✗ docker run hello-world --name hhbcreate
        docker: Error response from daemon: OCI runtime create failed: container_linux.go:370: starting container process caused: exec: "--name": executable file not found in $PATH: unknown.
        ERRO[0000] error waiting for container: context canceled 




docker ps                   => 查看当前运行的容器信息
docker ps -q                => 静默模式,仅列出当前运行的容器ID
docker ps -a                => 查看所有的容器信息(包括当前运行的和历史运行过的容器)
docker ps -l                => l: last, 列出上一次运行的容器信息
docker ps -n 5              => 列出上5次运行的容器信息

docker start e4c3013031f4   => 启动容器
docker stop e4c3013031f4    => 停止容器(开始 -> 电源 -> 关机)
docker kill e4c3013031f4    => 强制停止容器(拔电源)
docker restart e4c3013031f4 => 重启容器

docker rm e4c3013031f4      => 删除已停止的容器(若容器正在运行,可能提示删除冲突)
docker rm e4c3013031f4 -f   => 强制删除容器(可删除正在运行的容器)


# 容器和宿主机互相Copy文件
docker cp e4c3013031f4:/home/test.txt /root/test.txt
docker cp /root/test e4c3013031f4:/home/test.txt


docker rm $(docker ps -aq)      => 方式1:删除所有容器
docker ps -aq | xargs docker rm => 方式2:删除所有容器

docker network ls               => 列出容器网桥


退出容器:
    exit         => 关闭容器并退出
    Ctrl + P + Q => 容器不停止退出


docker attach f67589c50f57                        => 重新进入还在运行的容器,不会启动新的进程

docker exec -t 84013b0e931c ls -l /tmp            => 在宿主系统上(不进入到容器内)执行某已存在容器内的命令
docker exec -t 84013b0e931c /bin/bash             => 进入容器并执行/bin/bash命令


docker top f67589c50f57                           => 查看容器内运行的进程信息

docker inspect {docker_id}                        => 查看容器内部细节
docker inspact {docker_name}

docker cp 84013b0e931c:/tmp/hhb.txt .             => 将容器内文件 /tmp/hhb.txt COPY到宿主机器当前目录下

docker volume ls                                  => 列出容器卷


docker logs
    -f: 跟随最新的日志打印
    -t: 时间戳
    --tail n: 显示最后 n 条

    docker run -d ubuntu /bin/bash -c "while true; do echo hello hhb; sleep 5; done"           # 人为设置一个持续运行的进程

    docker logs f67589c50f57                      => 打印某容器内的全部日志信息
    docker logs -f f67589c50f57                   => 追加打印某容器内的日志信息
    docker logs -t f67589c50f57                   => 打印某容器内的日志信息和日志对应的时间戳
    docker logs --tail 3 f67589c50f57             => 打印某容器内最新3条日志信息
    docker logs -ft --tail 3 f67589c50f57         => 命令的组合运用





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

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

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

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

docker镜像加载原理:

    docker 镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS.


    kernal -> centos -> jdk8 -> tomcat  => 分层的镜像

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


docker commit => 提交对当前容器的修改使之成为一个新的镜像
    docker commit -m="提交的描述信息" -a="作者" 容器ID 目标镜像名称:TAG名称   => docker commit 命令格式

    Scenario:
        1. docker run -it -p 8888:8080 tomcat
        2. cd /usr/local/tomcat/weapps; rm -rf docs
        3. docker commit

        docker commit -a="hhb" -m="tomcat without docs" f67589c50f57 hhb/tomcat_new:2.0  (f67589c50f57为当前正在运行且已被修改的容器)

        docker run -it -p 7777:8080 hhb/tomcat_new:2.0


docker 数据卷

- 容器的持久化
- 容器间继承 + 数据共享


docker理念:
    - 将应用与运行环境打包形成容器运行,运行可以伴随着容器,但是我们对数据的要求希望时持久化的
    - 容器之间希望有可能共享数据

docker 容器产生的数据,如果不通过 docker commit 生成新的镜像,使得数据成为镜像的一部分保存下来,那么当容器被删除后,数据自然也就没有了。为了保存docker中的数据,我们使用卷。

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

特点:
    - 数据卷可在容器之间共享或重用数据
    - 卷中的更改可以直接生效
    - 数据卷中的更改不会包含在镜像的更新中
    - 数据卷的生命周期一直持续到没有容器使用它为止
    - 数据卷可以实现容器到宿主机或宿主机到容器之间的数据共享

NOTE: 容器被停止后,对主机数据卷的更新同样会同步到容器中,当容器被重新启动时,更新生效


命令行方式添加数据卷:
    docker run -it -v /宿主机目录:/容器内目录:权限配置 镜像名
    docker run -it -v /home/hhb/hhbdata:/home/hhb/hhbvolume ubuntu   (目录不存在时会自动创建,未指定读写权限时默认有读写权限)


        docker inspect ac96d974ee14  => 验证数据卷是否绑定成功

            "HostConfig": {
                "Binds": [
                    "/home/hhb/hhbdata:/home/hhb/hhbvolume"
                ],
                "ContainerIDFile": "",
                "LogConfig": {
                    "Type": "json-file",
                    "Config": {}
                },
            }

            "Mounts": [
                {
                    "Type": "bind",
                    "Source": "/home/hhb/hhbdata",
                    "Destination": "/home/hhb/hhbvolume",
                    "Mode": "",
                    "RW": true,
                    "Propagation": "rprivate"
                }
            ],

    docker run -it -v /home/hhb/hhbdata:/home/hhb/hhbvolume:ro ubuntu  => 设置容器内只读权限(ro),容器内不可更新编辑数据卷内容,宿主机对数据卷的更新操作不受影响

            "Mounts": [
                {
                    "Type": "bind",
                    "Source": "/home/hhb/hhbdata",
                    "Destination": "/home/hhb/hhbvolume",
                    "Mode": "ro",
                    "RW": false,
                    "Propagation": "rprivate"
                }
            ],

        root@2680dc0d078e:/home/hhb/hhbvolume# touch ro.txt
        touch: cannot touch 'ro.txt': Read-only file system

    NOTE: docker 挂载宿主机目录访问出现 cannot open directory .: Permissionn denied  => 解决办法:在挂载目录后多加一个 --privileged=true 参数
    docker run -it -v /home/hhb/hhbdata:/home/hhb/hhbvolume --privileged=true ubuntu


通过DockerFile方式添加卷:
    VOLUME ["/dataVolumeContainer", "/dataVolumeContainer2", "/dataVolumeContainer3"]

    说明:
        处于可移植和分享的考虑,用 -v 宿主机目录:容器内目录 这种方法不能直接在DockerFile 中实现
        由于宿主机目录是依赖于特定宿主机的,并不能保证在所有的宿主机上都存在这样的特定目录。


    DockerFile:

    vim /home/hhb/DockerFile
        FROM ubuntu
        VOLUME ["/dataVolumeContainer", "/dataVolumeContainer2"]
        CMD echo "finished, successed"
        CMD /bin/bash


    docker build -f /home/hhb/DockerFile -t hhb/ubuntu .

        ➜  ~ docker build -f DockerFile -t hhb/ubuntu:custom_1.0 .
        [+] Building 0.4s (5/5) FINISHED                                                                                                            
        => [internal] load build definition from DockerFile                                                                                   0.1s
        => => transferring dockerfile: 157B                                                                                                   0.0s
        => [internal] load .dockerignore                                                                                                      0.1s
        => => transferring context: 2B                                                                                                        0.0s
        => [internal] load metadata for docker.io/library/ubuntu:latest                                                                       0.0s
        => [1/1] FROM docker.io/library/ubuntu                                                                                                0.1s
        => => resolve docker.io/library/ubuntu:latest                                                                                         0.0s
        => exporting to image                                                                                                                 0.0s
        => => exporting layers                                                                                                                0.0s
        => => writing image sha256:466c05608a0a3bb9fa1703b9c52372af63380956206e155a2a0c6cdaa9b7c9a1                                           0.0s
        => => naming to docker.io/hhb/ubuntu:custom_1.0                                                                                       0.0s



        NOTE:DockerFile 中虽未映射宿主机的数据卷,执行 docker build 命令后,会自动将容器中的数据卷映射到主机数据卷

            "Mounts": [
                {
                    "Type": "volume",
                    "Name": "1c0399eab660f590fe60994c35077d61b74a36f0856a08059f1ee4073166fcb9",
                    "Source": "/var/lib/docker/volumes/1c0399eab660f590fe60994c35077d61b74a36f0856a08059f1ee4073166fcb9/_data",
                    "Destination": "/dataVolumeContainer2",
                    "Driver": "local",
                    "Mode": "",
                    "RW": true,
                    "Propagation": ""
                },
                {
                    "Type": "volume",
                    "Name": "a0da56cd9ce7bbbbdd8f86efc321a74a454c202e57dec19555cea0de09baa6c4",
                    "Source": "/var/lib/docker/volumes/a0da56cd9ce7bbbbdd8f86efc321a74a454c202e57dec19555cea0de09baa6c4/_data",
                    "Destination": "/dataVolumeContainer",
                    "Driver": "local",
                    "Mode": "",
                    "RW": true,
                    "Propagation": ""
                }
            ]



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

docker run -it --name dc01 hhb/ubuntu:custom_1.0

dc02,dc03 继承 dc01 => 

    docker run -it --name dc02 --volumes-from dc01 hhb/ubuntu:custom_1.0
    docker run -it --name dc02 --volumes-from dc03 hhb/ubuntu:custom_1.0


NOTE:子级和父级的任何更新都同步给彼此,即使后面父级容器被删除了,数据共享仍然不受影响 => 容器之间配置信息的传递,数据卷的生命周期一直持续到没有容器使用它为止


DockerFile

1. Dockerfile 
2. docker build
3. docker run


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


Dockerfile 语法基础:
    - 每条保留字指令都必须为大写字母且后面至少包含一个参数
    - 指令从上到下依次执行
    - # 表示注释
    - 每条指令都会创建一个新的镜像层,并对镜像进行提交


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



Dockerfile 保留字指令:
    FROM:       基础镜像,表明当前镜像是基于哪个基础镜像的
    MAINTAINER: 镜像维护者信息,姓名和邮箱
    RUN:        容器构建时需要运行的命令
    EXPOSE:     对外暴露的端口
    WORKDIR:    指定在创建容器后,终端默认登录进来的工作目录(未指定时,默认为根目录)
    ENV:        用来在构建镜像过程中设置环境变量(环境变量可以在后续的任何RUN指令中使用,也可以在其它指令中使用这些环境变量,如: ENV MY_PATH /usr/mytest  => WORKDIR $MY_PATH)
    ADD:        将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL和解压tar压缩包
    COPY:       类似ADD,拷贝文件和目录到镜像中(将从构建上下文目录中 <源路径>的 文件/目录 复制到新的一层的镜像内的 <目标路径> 位置)
    VOLUME:     容器数据卷,用于数据保存和持久化工作
    CMD:        指定一个容器启动时要运行的命令(Dockerfile 中可以指定多个CMD命令,但只有最后一个生效,CMD 会被 docker run 之后的参数替换)
    ENTRYPOINT: 指定一个容器启动时要运行的命令(ENTRYPOINT的目的和CMD一样,都是在指定容器启动程序及参数,docker run 之后的参数会追加到ENTRYPOINT之后而不是替换)
    ONBUILD:    当构建一个被继承的Dockerfile时运行命令,父镜像在被子镜像继承后父镜像的onbuild被触发




场景1:自定义myubuntu,要求如下:
    - 重新设置登录后的默认路径
    - vim编辑器
    - 支持 ifconfig 命令

    Dockerfile_01

        FROM centos
        MAINTAINER huabo<hhbstar@hotmail.com>
        ENV MYPATH /tmp
        WORKDIR $MYPATH

        RUN yum -y install vim-nox
        RUN yum -y install net-tools

        EXPOSE 80

        CMD echo $MY_PATH
        CMD echo "build success"

        CMD /bin/bash



docker history  => 列出镜像的变更历史

    ➜  ~ docker history a61170b45d0f
    IMAGE          CREATED          CREATED BY                                      SIZE      COMMENT
    a61170b45d0f   11 minutes ago   CMD ["/bin/sh" "-c" "/bin/bash"]                0B        buildkit.dockerfile.v0
    <missing>      11 minutes ago   CMD ["/bin/sh" "-c" "echo \"build success\""]   0B        buildkit.dockerfile.v0
    <missing>      11 minutes ago   CMD ["/bin/sh" "-c" "echo $MY_PATH"]            0B        buildkit.dockerfile.v0
    <missing>      11 minutes ago   EXPOSE map[80/tcp:{}]                           0B        buildkit.dockerfile.v0
    <missing>      11 minutes ago   WORKDIR /tmp                                    0B        buildkit.dockerfile.v0
    <missing>      11 minutes ago   ENV MYPATH=/tmp                                 0B        buildkit.dockerfile.v0
    <missing>      11 minutes ago   MAINTAINER huabo<hhbstar@hotmail.com>           0B        buildkit.dockerfile.v0
    <missing>      2 weeks ago      /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B        
    <missing>      2 weeks ago      /bin/sh -c mkdir -p /run/systemd && echo 'do…   7B        
    <missing>      2 weeks ago      /bin/sh -c [ -z "$(apt-get indextargets)" ]     0B        
    <missing>      2 weeks ago      /bin/sh -c set -xe   && echo '#!/bin/sh' > /…   811B      
    <missing>      2 weeks ago      /bin/sh -c #(nop) ADD file:4f15c4475fbafb3fe…   72.9MB


场景2:CMD VS ENTRYPOINT => 都是指定一个容器启动时要运行的命令(CMD 覆盖、ENTRYPOINT追加)

    Dockerfile_02

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

        => docker run a61170b45d0f -i
            => System Error: exec "-i"


        ==> 

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


场景3: ONBUILD (父镜像中包含了ONBUILD时,子镜像构建时会自动触发父镜像ONBUILD对应的命令)

    DockerFile_father:

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


    docker build -f DockerFile_father -t DockerFile_father .

    DockerFile_child:

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

    docker build -f DockerFile_father -t DockerFile_child .


场景4: COPY & ADD (COPY 复制;ADD 复制并解压缩)

    1. mkdir -p /home/hhb/hhbdata
    2. touch copy.txt
    3. cp /opt/apache-tomcat-9.0.8.tar.gz .;cp /opt/jdk-8u171-linux-x64.tar.gz .

    4. 在/home/hhb/hhbdata新建Dockerfile 文件
    5. build
    6. run
    7. 验证
    8. release

    ls /home/hhb/hhbdata
    copy.txt
    /opt/apache-tomcat-9.0.8.tar.gz

    Dockerfile_03:
        FROM centos
        MAINTAINER hhb<hhb@hotmail.com>

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

        #把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 MY_PATH /usr/local/
        WORKDIR $MY_PATH

        #配置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 80

        # 启动时运行 tomcat
        #ENTRYPOINT ["/usr/local/apache-tomcat-9.0.8/bin/startup.sh"]
        #CMD ["/usr/local/apache-tomcat-9.0.8/bin/catlina.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

docker run

 docker run -d -p 8090:8080 --name mytomcat9
 -v /home/hhb/hhbdata/test:/usr/local/apache-tomcat-9.0.8/webapps/test
 -v /home/hhb/hhbdata/tomcat9logs:/usr/local/apache-tomcat-9.0.8/webapps/logs
 --privileged=true
 hhbtomcat9



 docker run -p 12345:3306 --name mysql 
 -v /home/hhb/mysql/conf:/etc/mysql/conf.d 
 -v /home/hhb/mysql/logs:/usr/local/logs
 -v /home/hhb/mysql/data:/var/lib/mysql 
 -e MYSQL_ROOT_PASSWORD=123456 
 -d mysql:latest


 docker exec  a61170b45d0f /bin/bash
 mysql -uroot -p

 #备份dockers容器数据库数据到宿主机
 dokcer exec a61170b45d0f sh -c 'exec mysqldump --all-databases -uroot -p"123456"' > /home/hhb/mysql/data/alll-databases.sql



 docker pull redis 

 docker run -p 6379:6379 
 -v /home/hhb/redis/data:/usr/local/data
 -v /home/hhb/redis/conf/redis.conf:/usr/local/etc/redis/redis.conf
 -d redis:latest redis-server /usr/local/etc/redis/redis.conf
 --appendonly yes

 NOTE: 
     - /home/hhb/redis/conf/redis.conf 为文件夹
     - --appendonly yes 配置持久化

 设置 /home/hhb/redis/conf/redis.conf/redis.conf

 docker exec -it a61170b45d0f redis-cli


docker push

 docker commit -a="hhb" -m="update" a61170b45d0f mycentos:1.1
 docker tag a61170b45d0f registry.cn-hangzhou.aliyuncs.com/hehuabo/mycentos:1.1
 docker push registry.cn-hangzhou.aliyuncs.com/hehuabo/mycentos:1.1

 docker pull registry.cn-hangzhou.aliyuncs.com/hehuabo/mycentos:1.1  (公网下载镜像)


容器编排

1.安装
sudo curl -L "https://github.com/docker/compose/releases/download/v2.2.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose


2.查看版本
docker-compose -v


3.编写 docker-compose.yml 文件
version: '3.8'
services:
  jenkins:
    image: jenkins/jenkins:lts
    ports:
      - 8000:8080
    volumes:
      - /home/hhb/dev/docker_volumns/jenkins:/var/jenkins_home


4.启动容器
docker-compose up


5.访问UI界面查看效果 http://127.0.0.1:8000


6.设置Jenkins密码
cat /home/hhb/dev/docker_volumns/jenkins/secrets/initialAdminPassword


7.Creating a Dev Container

docker-compose.yml
version: "3.8"
services:
    app:
        build: ./
        ports:
            - 3000:3000

=>

version: "3.8"
services:
    app:
        image: node:lts-alpine
        command: sh -c "npm install && npm run dev"
        working_dir: /app
        volumes:
            - nodemodules:/app/node_modules
            - ./:/app
        ports:
            - 3000:3000
volumes:
    nodemodules:


8.Using Multi-Stage Dockerfile
Dockerfile

FROM node:lts-alpine AS base
WORKDIR /app
COPY package.json yarn.lock ./
RUN yarn install --production && yarn cache clean
COPY src ./src
CMD ["node", "/app/src/index.js"]

=>

FROM node:lts-alpine AS base
WORKDIR /app
COPY package.json yarn.lock ./

FROM base AS dev
RUN yarn install && yarn cache clean
CMD ["npm", "run", "dev"]

FROM base AS prod
RUN yarn install --production && yarn cache clean
COPY src ./src
CMD ["node", "/app/src/index.js"]

=> docker-compose.yml

version: "3.8"
services:
    app:
        build:
            context: .
            target: dev
        volumes:
            - nodemodules:/app/node_modules
            - ./:/app
        ports:
            - 3000:3000
volumes:
    nodemodules:


9.frontend/backend service
docker-compose.yml

version: "3.8"

services:
    frontend:
        build: ./frontend
        ports:
            - 3000:3000
    backend:
        build: ./backend
        ports:
            - 3001:3001
        environment:
            DB_URL: mongodb://db/hhb
    db:
        image: mongo:4.0-xenial
        ports:
            - 27017:27017
        volumes:
            - mongo_data:/data/db

volumes:
    mongo_data:


10.docker network
    docker network create hello-pdc-net
    docker run --rm --name app --net hello-pdc-net -d -p 5000:80 hello-pdc
    docker run --rm --name redis --net hello-pdc-net -d redis:alpine

最佳实践

  1. 不要一有变更就去构建你的容器

  2. 将你的源代码挂载到容器中,一有代码变更自动生效,无须重复构建容器


Docker 可视化工具

1.安装 Portainer (官网安装说明:https://www.portainer.io/installation/)
docker pull portainer/portainer

2.新建容器卷
docker volume create portainer_data

3.运行容器
docker run -d -p 8000:8000 -p 9000:9000 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data_portainer/portainer

4.访问UI界面 http://localhost:9000



拓展阅读