zoukankan      html  css  js  c++  java
  • docker深入

    docker深入

     

    来源:尚硅谷教程

    docker在线操作:https://labs.play-with-docker.com/

     

    docker是什么

    docker的出现是为了解决什么样的痛点?

    docker理念

    docker能干嘛

    之前的虚拟化技术

    容器虚拟化技术

    why docker

    docker安装

    docker核心概念

    docker安装

    docker镜像加速

    docker底层原理

    工作原理

    为什么docker比VM快

    docker命令

    帮助命令

    镜像命令

    容器命令

    重要命令

    docker镜像

    是什么

    联合文件系统的概念

    docker镜像加载原理

    分层的镜像

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

    特点

    Docker镜像commit操作补充

    docker容器数据卷

    是什么

    能干嘛

    数据卷

    直接命令添加

    DockerFile添加

    数据卷容器

    是什么

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

    DockerFile解析

    是什么

    DockerFile构建过程解析

    Dockerfile内容基础知识

    Docker执行Dockerfile的大致流程

    DockerFile保留字指令

    FROM

    MAINTAINER

    RUN

    EXPOSE

    WORKDIR

    ENV

    ADD

    COPY

    VOLUME

    CMD

    ENTRYPOINT

    ONBUILD

    CMD和ENTRYPOINT的差异

    DockerFile自定义镜像mycentos

    DockerFile自定义镜像Tomcat

    docker安装mysql

    docker安装redis

    本地镜像推送阿里云

    Alpine Linux构建镜像遇到的问题

    清理docker磁盘占用

    清理容器占用磁盘

    限制容器日志大小

     

     

    docker是什么

    docker的出现是为了解决什么样的痛点?

    docker理念

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

     

    docker能干嘛

    之前的虚拟化技术

    容器虚拟化技术

    why docker

    docker安装

    docker核心概念

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

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

     

    仓库(Repository):是集中存放镜像文件的场所。仓库(Repository)和仓库注册服务器(Registry)是有区别的。仓库注册服务器上往往存放着多个仓库,每个仓库中又包含了多个镜像,每个镜像有不同的标签(tag)。

    仓库分为公开仓库和私有仓库两种,最大的公开仓库是Docker Hub,存放了数里庞大的镜像供用户下载。国内的公开仓库包括阿里云、网易云等。

    docker安装

    具体参见中文官网

    安装需要注意的是centos6和centos7安装方式有些差异,需要注意。

    # centos7安装完docker后
    
    # 查看版本
    docker version
    # 启动docker进程
    sudo systemctl start docker
    # 停止docker
    sudo systemctl stop docker

    docker镜像加速

    阿里云镜像加速:

    1.注册阿里云镜像账户。

    2、在镜像中心-镜像加速器中获取自己ide镜像地址,按照上面的操作指示在自己系统设置即可。

     

    docker底层原理

    工作原理

    为什么docker比VM快

    (1)docker有着比虚拟机更少的抽象层。由亍docker不需要Hypervisor实现硬件资源虚拟化,运行在docker容器上的程序直接使用的都是实际物理机的硬件资源。因此在CPU、内存利用率上docker将会在效率上有明显优势。

     

    (2)docker利用的是宿主机的内核,而不需要Guest OS。因此,当新建一个容器时,docker不需要和虚拟机一样重新加载一个操作系统内核。仍而避免引寻、加载操作系统内核返个比较费时费资源的过程,当新建一个虚拟机时,虚拟机软件需要加载Guest OS,返个新建过程是分钟级别的。而docker由于直接利用宿主机的操作系统,则省略了返个过程,因此新建一个docker容器只需要几秒钟。

     

     

    docker命令

    帮助命令

    docker version 
    docker info
    docker help

    镜像命令

    # 列出本地的镜像
    docker images [options]
    
    # 列出本地镜像,含中间镜像层
    docker images -a
    
    # 只显示镜像ID
    docker images -q
    
    # 显示镜像ID,包含中间镜像层的ID
    docker images -qa
    
    # 显示摘要信息
    docker images --digests
    
    # 显示完整的镜像信息,不要截断输出
    docker images --no-trunc

    docker hub搜索中镜像:

    # 从docekr hub上搜索镜像
    docker search [options] imagename
    
    # 例如
    docker search tomcat
    
    # 搜索点赞数超过三十的该镜像
    docker search -s 30 tomcat
    
    # 显示完整镜像信息
    docker search -s 30 --no-trunc tomcat
    
    # 只列出automated build类型的镜像
    docker search --automated tomcat

    下载镜像:

    # 没写版本号,自动拉取最新版
    docker pull imagename # 等价于docker pull imagename:latest

    删除镜像:

    # 删除镜像,如果没写版本,默认删除lastest。
    docker rmi imagename
    
    不能删除一个已经创建容器的镜像。
    docker run hello-world
    docker rmi hello-world
    # 报错信息可看到hello-world镜像分为了两层,要删除hello-world镜像时,报错提示无法删除,因为它被其他层引用着。
    Error response from daemon: conflict: unable to remove repository reference "hello-world" (must force) - container ee20158ca82c is using its referenced image fce289e99eb9
    
    # 强制删除该镜像,删单个
    docker rmi -f imagename
    
    # 删除多个
    docker rmi -f imagename1 imagename2 ...
    
    # 删除全部,使用类似java EL表达式,使用$(执行的子命令)
    docker rmi -f $(docker images -q)

    查看镜像变更历史:

    docker history imageid

    容器命令

    运行容器:

     

    # docker可以run镜像名或镜像id
    docker run [options] image [command][arg...]
    
    options说明(常用):
        --name="容器的新名字":为容器指定一个名字
        -d:以后台进程的方式运行容器,并返回容器id,也即启动守护式容器;
        -i:以交互模式运行容器,通常与-t同时使用
        -t:为容器重新分配一个伪输入终端,通常与-i同时使用
        -P:随机端口映射
       -p:指定端口映射,有以下四种格式
            ip:hostPort:condatinerPort
            ip::containerPort
            hostPortLcontainerPort
            containerPort
            
    # 当使用-it时会一直保持着容器的启动可以防止容器运行完即停止

                 

    # -i 和-t可合一起启动        
    docker run -it centos
    
    # 使用exit退出伪终端并关闭容器
    # Ctrl+P+Q 退出伪终端进入宿主机,但不关闭容器。

     

    列出所有运行的容器:

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

    启动容器:

    docker start containername/containerid

    重启容器:

    docker restart containername/containerid

    停止容器:

    # 慢慢的停止
    docker stop containername/containerid
    
    # 强制关闭,迅猛粗暴
    docker kill -f containername/containerid

    删除已停止的容器:

    docker rm containername/containerid
    
    # 删除所有
    docker rm $(docker ps -qa)
    
    # 将|之前命令查出来的结果传递到xargs命令的后面
    docker pa -a -q|xargs docker rm

    重要命令

    # 守护进程启动容器
    docker run -d imagename

    如下图,使用守护进程的模式去运行centos,执行docker run后确确实实返回给了我们一个容器ID,说明我们启动成功了,但是使用docker ps却查看不到这个容器的信息。这是为何?

    既然查不到这个容器在运行,那就说明这个容器已经退出了,它确实短暂的存在过,但是一瞬间就退出了。

    # 查看容器日志
    docker logs -f -t --tail 容器ID
    
    -t 时加入时间戳
    -f 跟随最新的日志打印
    --tail 数字显示最后多少条
    # 查看容器内运行的进程
    docker top 容器ID
    # 查看容器内部细节,返回的时json对象
    docker inspect 容器ID
    # 进入正在运行的容器并以命令行交互,上面我们使用exit或Ctrl P Q退出容器内的交互环境
    # 如果是使用Ctrl P Q退出,我们并没有关闭容器,那我们怎么再次进入?两种方式
    1、docker exec -it 容器ID bashShell  
    #例如: exec可以直接在容器外操作容器里面的内容
        docker exec -it c9ef60079a8a ls -a 
    #例如: exec还可以使用这种方式达到和aeeach一样的效果,就是进入容器内操作里面的内容
        docker exec -it c9ef60079a8a /bin/bash
    
    2、 docker attach 容器ID
    
    两者区别:
        attach:直接进入容器启动命令的终端,不会启动新的进程。
        exec:是在容器内打开新的终端,并且可以启动新的进程。

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

     

    docker镜像

    是什么

    联合文件系统的概念

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

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

     

    kernel操作系统内核。

    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。

     

     

    分层的镜像

    以我们的pull为例,在下载的过程中我们可以看到docker的镜像好像是在一层一层的在下载

     

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

    最大的一个好处就是 - 共享资源

     

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

     

    特点

    Docker镜像都是只读的。

    当容器启动时,一个新的可写层被加载到镜像的顶部。

    这一层通常被称作“容器层”,“容器层”之下的都叫"镜像层"。

    Docker镜像commit操作补充

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

    啥是容器副本?比方说你从镜像库里拉取了一个标准版的tomcat镜像,然后你对该镜像启动的tomcat容器做了一些修改或者配置,此时此刻,你修改的这个tomcat容器并不是原来标准的tomcat镜像启动的容器了,而是标准tomcat容器的一个副本容器。

    # 如果没写标签名,默认为latest
    docker commit -m="提交的描述信息" -a="作者" 容器ID 要创建的目标镜像名:[标签名]

     

    思维导图中的按照的tomcat是tomcat7,因为如果你默认安装tomcat8或其以上是没有webapps目录的,也就是即使你启动了8080端口的tomcat也看不到任何页面:

    docker pull tomcat:7-jre7

     

    docker容器数据卷

    是什么

    先来看看Docker的理念:

    将运用与运行的环境打包形成容器运行 ,运行可以伴随着容器,但是我们对数据的要求希望是持久化的

    容器之间希望有可能共享数据

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

    类似于一个主机上的移动硬盘。

     

    能干嘛

    卷就是目录或文件,存在于一个或多个容器中,由docker挂载到容器,但不属于联合文件系统,因此能够绕过Union File System提供一些用于持续存储或共享数据的特性:

     卷的设计目的就是数据的持久化,完全独立于容器的生存周期,因此Docker不会在容器删除时删除其挂载的数据卷。

    特点:

    1:数据卷可在容器之间共享或重用数据

    2:卷中的更改可以直接生效

    3:数据卷中的更改不会包含在镜像的更新中

    4:数据卷的生命周期一直持续到没有容器使用它为止

    5:能实现容器数据到宿主机,宿主机数据到容器。

    6:可以绑定多个卷【使用dockerfile】。

     

    数据卷

    直接命令添加

    添加数据卷的命令

    docker run -it -v /宿主机绝对路径目录:/容器内目录 镜像名
    
    # 案例:如果目录不存在,docker会自己建立。将容器上的数据和宿主机上的数据绑定在一起。
    docker run -it -v /hostVolumeData:/containerVolumeData centos

    查看数据卷是否挂载成功

    docker inspect 561f321d20cc

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

    我在宿主机上的和容器绑定的文件夹里创建一个新的文件后,发现容器内和宿主机绑定的文件夹下也出现了这个文件。

    在容器内的该test.txt文件夹里写点东西,发现宿主机里该文件的内容和容器内文件内容一致。

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

    停止容器后,主机新增一个log日志文件,再次start该容器,发现和主机绑定的文件夹又是同步的。

     

    命名带读写权限

    # 设置容器内对该文件夹里的内容只有读权限
    docker run -it -v /hostVolumeData:/containerVolumeData:ro image

     

    DockerFile添加

    VOLUME["/dataVolumeContainer1","/dataVolumeContainer2",...]
    
    # 出于可移植和分享的考虑,用-v主机目录:容器目录这种方法不能直接在Dockerfilet中实现。
    # 由于宿主机目录是依赖指定宿主机的,并不能保证在所有宿主机上都存在这样的特定目录。
    
    # 比方说在windows和linux上文件夹的结构并不相同,linux没有C盘一说,所有如果你使用
    # -v那种绑定的形式,可能在windows上就会出错。所以docker提供了在dockerfile里使用
    #VOLUME的方式去创建文件,且使用默认的方式[windows的就在某个目录创建文件关联,linux也一样]关联宿主机文件。

    3、Dockerfile文件构建

    # volume test
    FROM centos # 表示要构建的这个镜像依赖于centos父镜像
    VOLUME ["/dataVolumeC1","/dataVolumeC2"]
    CMD echo "finished,build volume!"
    CMD /bin/bash # 在run该镜像后直接进入bash 

    4、build后生成镜像

    docker build -f /dockerfile/Dockerfile -t liuwei/centos .
    
    # -f 表示指定构建的dockerfile文件位置
    # -t 表示镜像名
    # .表示在当前目录生成镜像文件

    5、已经指定容器的卷目录地址,那对应宿主机的文件地址在哪?

    docker inspect 109fe5b3ed45

     

    6、备注

    Docker挂载主机目录Docker访问出现cannot open directory .: Permission denied

    解决办法:在挂载目录后多加一个--privileged=true参数即可

     

    数据卷容器

    是什么

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

     

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

    1、以之前建立的centos/liuwei镜像创建一个容器

    docker run --name="con1" -it liuwei/centos
    
    # 此时此刻这个容器是已经挂载了两个数据卷的

    2、我们在创建两个容器挂载在con1上

    docker run --name="con2" -it --volumes-from con1 liuwei/centos
    
    docker run --name="con3" -it --volumes-from con1 liuwei/centos

    3、进入con1,查看两个文件卷都是空的,然后创建文件1

    4、分别进入con2、con3发现在卷里都出现了刚才con1创建的文件。con2创建log2.txt,con3创建log3.txt,查看con1也含有这些文件。

    5、删除con2和con3挂载的父容器con1

    docker rm -f con1

    6、再次进入con2、con3发现挂载卷还存在,里面的文件都存在。

     

    总结:

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

     

    DockerFile解析

    是什么

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

     

    DockerFile构建过程解析

    Dockerfile内容基础知识

    1、每条保留字指令都必须为大写字母且后面要跟随至少一个参数

    2、指令按照从上到下,顺序执行

    3、# 表示注释

    4、每条指令都会创建一个新的镜像层,并对镜像进行提交。

     

    Docker执行Dockerfile的大致流程

    1、docker从基础镜像运行一个容器。【scratch是一切镜像的祖先,相当于java里的object类】

    2、执行一条指令并对容器做出修改。

    3、执行类似docker commit的操作提交一个新的镜像层。

    4、docker在基于刚提交的镜像运行一个新容器。

    5、执行dockerfile中的下一条指令直到所有指令都执行完成。

    DockerFile保留字指令

    FROM

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

     

    MAINTAINER

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

     

    RUN

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

     

    EXPOSE

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

     

    WORKDIR

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

     

    ENV

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

    ENV MY_PATH /usr/test

    这个环境变量可以在后续的任何RUN指令中使用,这就如同在命令前面定义了环境变量前缀一样;也可以在其他指令中直接使用这些环境变量。比如:WORKDIR:$MY_PATH

     

    ADD

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

     

    COPY

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

    COPY src dest
    COPY ["src","dest"]

     

    VOLUME

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

     

    CMD

    指定一个容器启动时要运行的命令。他和RUN命令后面加参数格式类似。

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

     

    ENTRYPOINT

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

     

    ONBUILD

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

     

    CMD和ENTRYPOINT的差异

    Dockerfile文件中CMD和ENTRYPOINT都可以给容器设置启动参数,二者采用的方式是追加的方式,但CMD只要最后一个才生效。

    比如说:在centos镜像的dockerfile文件里如下:

    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="20191001"
    
    CMD ["/bin/bash"]

     

    如过我运行这个容器使用如下方式:

    docker run -it centos ls -a

    那就相当于我们在dockerfile文件最后追加了 ls -a

    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="20191001"
    
    CMD ["/bin/bash"]
    CMD ls -a

    又由于CMD指定的命令只有最后一个生效,所有centos容器并没有被启动!!!

     

    假如centos最后不是使用CMD而是采用如下:

    ENTRYPOINT ["/bin/bash"]

    那么我们使用如下命令:

    docker run -it centos ls -a

    就相当于dockerfile文件最后变成这样:

    ENTRYPOINT ["/bin/bash"]
    ENTRYPOINT ["ls -a"]
    # 也就如下:
    ENTRYPOINT ["/bin/bash","ls -a"]

     

    DockerFile自定义镜像mycentos

    启动最初始的centos镜像,使用vim命令创建打开一个文件,发现精简版的centos不支持该命令,那我们自定义一个支持vim命令的镜像。

    1、编写镜像文件

    FROM centos
    
    MAINTAINER liuwei<1111111@qq.com> # 设置镜像维护者
    
    ENV HOME_PATH /home # 设置变量
    
    WORKDIR $HOME_PATH # 设置容器启动后进入的落脚点
    
    CMD echo 'install vim'
    
    RUN yum -y install vim # 安装vim
    
    CMD echo 'install vim over!'
    
    EXPOSE 80
    
    CMD /bin/bash

    2、构建

     

    docker build -f /dockerfile/dockerfile2 -t vim/centos .

    3、运行并测试vim能否使用

    docker run vim/centos
    # vim可以使用

    4、列出镜像变更历史

    docker history imageid

     

    DockerFile自定义镜像Tomcat

    1、tomcat的运行依赖于jdk,所以我们要先把这两个tar.gz包down下来

    wget http://download.oracle.com/otn-pub/java/jdk/8u171-b11/512cd62ec5174c3487ac17c61aaa89e8/jdk-8u171-linux-x64.tar.gz
    
    wget https://mirrors.tuna.tsinghua.edu.cn/apache/tomcat/tomcat-8/v8.5.53/bin/apache-tomcat-8.5.53.tar.gz

    2、新建copy.txt用于马上测试copy命令。

    3、编写Dockerfile

    FROM centos
    
    MAINTAINER liuwei<111111@qq.com>
    
    ENV HOME_PATH /home/liuwei
    
    WORKDIR $HOME_PATH
    
    COPY copy.txt /usr/local/copy_container.txt
    
    RUN yum -y install vim
    
    # 在加之前你要先解压以下看看默认解压后的文件名是啥,因为下一步要用到
    # 把java和tomcat添加到容器
    ADD OpenJDK8U-jdk_x64_linux_openj9_8u242b08_openj9-0.18.1.tar.gz /usr/local/
    ADD apache-tomcat-8.5.53.tar.gz /usr/local/
    
    # 配置环境变量
    ENV JAVA_HOME /usr/local/jdk8u242-b08
    ENV CLASS_PATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
    ENV CATALINA_HOME /usr/local/apache-tomcat-8.5.53
    ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
    
    # 容器运行时监听的端口
    EXPOSE 8080
    
    # 启动时运行tomcat
    # ENTRYPOINT ["/usr/local/apache-tomcat-8.5.53/bin/startup.sh"]
    # CMD ["/usr/local/apache-tomcat-8.5.53/bin/catalina.sh","run"]
    
    # 启动tomcat并将日志实时输入到log目录下的.out文件里
    CMD /usr/local/apache-tomcat-8.5.53/bin/startup.sh && tail -F /usr/local/apache-tomcat-8.5.53/logs/catalina.out

    4、启动

    docker run -d -p 8080:8080 mytomcat:1.1
    
    # 上面启动方式不好的地方:
        # 1:启动看不到启动日志,如果出错了咋办,而且我就想以后台进程方式启动
        # 2:我既然启动tomcat肯定是要部署项目,我部署咋部署?
        
    # 解决以上问题:
    docker run -d -p 8080:8080 
    -v /usr/local/tomcat8/logs/:/usr/local/apache-tomcat-8.5.53/logs/ 
    -v /usr/local/webapps/:/usr/local/apache-tomcat-8.5.53/webapps/ 
    mytomcat:1.1
    
    # 如上我们使用两个数据卷文件夹绑定在宿主机上,既可以查看tomcat日志,又
    # 可以在宿主机上直接部署项目。
    
    # 经过我的尝试发现并不行,我直接不挂数据卷能运行,挂数据卷容器启动后访问不了页面。
    
    # 没办法我只好用以配置的方式去尝试一下
    # 在Dockerfile里在环境变量之前加了VOLUME
    VOLUME ["/usr/local/apache-tomcat-8.5.53/logs/","/usr/local/apache-tomcat-8.5.53/webapps/"]
    # 重新构建,run,成功访问!

    接下来就是把项目放到宿主机和容器绑定的webapps文件夹下了

    # 查看挂载生成的随机位置
    docker inspect 0a87d24975dc
    
    # 进入
    cd /var/lib/docker/volumes/1b15be4a96b0a72c7d1d57e49a065c60763dd30da3b6886a7dd107c85b2598f8/_data
    
    # 创建项目文件
    mkdir test
    
    # 创建web.xml,在创建index.jsp
    <?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>
    <%@ 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>

     

    访问http://localhost:8080/test/index.jspok

    我们稍微修改index.jsp在刷新看看是否同步,ok也没问题。

    接下来查看日志文件,刚才我们访问了两次:

    ok!

     

    docker安装mysql

    docker pull mysql:5.6
    
    # 安装docker hub mysql官网描述,该启动方式外部访问不到,没暴露对外端口
    docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
    
    # 常用配置
    docker run --name your_mysql_name 
    -v /home/liuwei/mysql_conf/:/etc/mysql/conf.d 
    -v /home/liuwei/mysql_log/:/logs 
    -v /home/liuwei/mysql_data/:/var/lib/mysql 
    -e MYSQL_ROOT_PASSWORD=your_mysql_root_pwd 
    -d -p 3306:3306 mysql:tag
    
    # 如上配置你可以在你的mysql_conf文件夹下创建my.cnf配置文件,他将同步到容器内,重启mysql容器
    # 后会加载这个配置文件。
    
    # 例如,我在mysql_conf/my.cnf里配置:
    [mysqld]
    default-time-zone = '+8:00'
    # docker restart mysql_container_id 
    # show variables like '%time_zone%';

    数据备份

    # 备份表结构及数据
    docker exec myql服务容器ID sh -c ' exec mysqldump --all-databases -uroot -p"123456" ' > /zzyyuse/all-databases.sql

     

    docker安装redis

    docker pull redis
    
    docker run --name docker-redis 
    -v /home/liuwei/redis_data:/data 
    -v /home/liuwei/redis_conf:/usr/local/etc/redis/redis.conf 
    -d -p 6379:6379 redis:tag redis-server /usr/local/etc/redis/redis.conf --appendonly yes
    # 在redis_conf新建redis.conf,具体配置参见数据库redis
    
    # 测试连接redis
    docker exec -it ac30dc29bb52 redis-cli
    127.0.0.1:6379> ping
    PONG

    测试持久化,当关闭redis时,数据被持久化到磁盘。

    本地镜像推送阿里云

    在阿里云创建自己的仓库,然后按照阿里云生成的命令提交即可。

    docker login --username=yourname docker_hub_host:ip
    
    docker logout docker镜像仓库
    
    docker login --username=admin --password='123456' 10.1.15.111:5000
    
    docker logout 10.1.15.111:5000

    Alpine Linux构建镜像遇到的问题

    Alpine Linux非常是和容器的使用,因为它小巧,功能完备,非常适合作为容器的基础镜像。

     

    解决方案详情参见:https://blog.csdn.net/weixin_39198406/article/details/90675645

     

    1、在使用python:3.6-alpine作为基础镜像勾选镜像时,安装mysqlclient出错,说找不到mysql-config文件,

    RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories
    RUN apk add gcc freetype-dev 
    RUN apk add gfortran musl-dev g++ libgcc libquadmath musl libgfortran 
    RUN apk add lapack-dev
    RUN apk add --no-cache mariadb-dev build-base

     

    2、pip安装时报错找不到某个包

    # 查看python里的pip支持的文件名和时间线
    >>> import pip._internal.pep425tags
    >>> print(pip._internal.pep425tags.get_supported())
    [<cp36-cp36m-win_amd64 @ 1625898767816>, <cp36-abi3-win_amd64 @ 1625898767944>, <cp36-none-win_amd64 @ 1625898768072>, <cp35-abi3-win_amd64 @ 1625898768200>, <cp34-abi3-win_amd64 @ 1625
    898768328>, <cp33-abi3-win_amd64 @ 1625898768520>, <cp32-abi3-win_amd64 @ 1625898768648>, <py36-none-win_amd64 @ 1625898768840>, <py3-none-win_amd64 @ 1625898768968>, <py35-none-win_amd
    64 @ 1625898769096>, <py34-none-win_amd64 @ 1625898769224>, <py33-none-win_amd64 @ 1625898769352>, <py32-none-win_amd64 @ 1625898769480>, <py31-none-win_amd64 @ 1625898769608>, <py30-no
    ne-win_amd64 @ 1625898769736>, <cp36-none-any @ 1625898769864>, <py36-none-any @ 1625898769928>, <py3-none-any @ 1625898769992>, <py35-none-any @ 1625898768392>, <py34-none-any @ 162589
    8770056>, <py33-none-any @ 1625898770120>, <py32-none-any @ 1625898770184>, <py31-none-any @ 1625898770248>, <py30-none-any @ 1625898770312>]
    
    # python版本-系统版本 @ 毫秒级时间
    import time
    >>> time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(1625898769))
    '2021-07-10 14:32:49'
    ERROR: Could not find a version that satisfies the requirement tensorflow==1.13.1 (from -r requirements.txt (line 11)) (from versions: none)
    ERROR: No matching distribution found for tensorflow==1.13.1 (from -r requirements.txt (line 11))

    原因是alpine安装的python包有要求,不能以manylinux_x86_x64的结尾格式),而你从网上下载的包里如果只有以系统后缀的该包,就会导致下载不被允许。所以这种情况下,推荐使用离线安装的方式,将你下载下来的那些以系统后缀命名的包改成none-any结尾即可。

    tensorflow下载:

    https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-1.13.1-cp36-cp36m-linux_x86_64.whl

    使用glibc:

    https://www.cnblogs.com/embedded-linux/p/12078154.html

     

     

    清理docker磁盘占用

    清理容器占用磁盘

    # 查看docker磁盘占用
    docker system df
    
    # 清理:删除关闭的容器、无用的数据卷和网络,以及无tag镜像
    docker system prune
    
    # 清理更加彻底:将没有容器使用的Docker镜像都删掉【慎用】
    docker system prune -a

     

    限制容器日志大小

    linux遇到的问题中,我的docker容器曾把磁盘写爆了。当时目录文件就是在/var/lib/docker中。这个目录包含了docker的所有相关文件,包括镜像、容器等。

    [root@localhost lib.linux-x86_64-3.6]# docker system df
    TYPE                TOTAL               ACTIVE              SIZE                RECLAIMABLE
    Images              26                  0                   10.48GB             10.48GB (100%)
    Containers          0                   0                   0B                  0B
    Local Volumes       12                  0                   250.9MB             250.9MB (100%)
    Build Cache         0                   0                   0B                  0B
    [root@localhost lib.linux-x86_64-3.6]# du -hs /var/lib/docker/
    11G     /var/lib/docker/
    [root@localhost lib.linux-x86_64-3.6]# cd /var/lib/docker/ & du
    ...
    80      ./network/files
    80      ./network
    0       ./swarm
    16      ./builder
    0       ./buildkit/content/ingest
    0       ./buildkit/content
    0       ./buildkit/executor
    56      ./buildkit
    0       ./tmp
    0       ./runtimes
    11230224    
    # 容器日志清0设置
    truncate -s 0 /var/lib/docker/containers/a376aa694b22ee497f6fc9f7d15d943de91c853284f8f10
    
    # 容器日志清0只是暂时办法,不管它的话它还会涨上去的,解决办法
    # vim /etc/docker/daemon.json
    
    {
      "log-driver":"json-file",
      "log-opts": {"max-size":"500m", "max-file":"3"}
    }
    # max-size:一个容器日志大小上限是500M
    # max-file,意味着一个容器有三个日志,分别是id+.json,id+1.json,id+2.json
    # 记得重启docker

     

     

     

    附上尚硅谷思维导图

    前进时,请别遗忘了身后的脚印。
  • 相关阅读:
    Flex Box 简单弹性布局
    CSS 0.5px 细线边框的原理和实现方式
    前端模块化方案全解(CommonJS/AMD/CMD/ES6)
    用信鸽来讲解HTTPS的知识
    __name__ == "__main__"的作用是什么?
    如何自学计算机科学与技术(Teach Yourself Computer Science)
    中文技术文档的写作规范
    'adb remount'的作用是什么?在什么情况下有用?
    使用python遍历文件夹取出特定的字符串
    Python&Appium实现安卓手机图形解锁
  • 原文地址:https://www.cnblogs.com/liudaihuablogs/p/13438611.html
Copyright © 2011-2022 走看看