zoukankan      html  css  js  c++  java
  • Dockerfile极简入门与实践

    前文中,罗列了docker使用中用到的基本命令
    此文,将会对怎样使用Dockerfile去创建一个镜像做简单的介绍

    Dockerfile命令

    要开始编写Dockerfile,首先要对相关的命令有个清晰的认识
    下面列出了部分Dockerfile命令的功能以及使用方法,供参考:

    1. FROM

    Dockerfile的第一条指定必须是FROM,用于指定基础镜像。
    用法:
    FROM [image]:[tag]

    2. MAINTAINER

    用于指定此Dockerfile维护者信息。
    用法:
    MAINTAINER <name> <email>

    3. ADD

    复制指定内容到镜像中,指定内容可以是一个相对或绝对路径,也可以是一个url(此时相当于wget),如果添加的文件是个tar压缩文件,文件在复制的时候会自动解压。
    用法:
    ADD <src> <dest>

    4. COPY

    与ADD命令用法相同,区别是COPY只能复制本地文件
    用法:
    COPY <src> <dest>

    5. RUN

    构建镜像时运行指定命令,建议多个命令尽量写在同一个RUN中,用&&分割或使用换行。
    用法:
    RUN <command>
    RUN ["executable", "param1", "param2"]
    前者在shell终端上运行,后者使用exec运行。

    6. CMD

    容器启动时运行指定命令,每个容器只能执行一条CMD命令,多个CMD命令时,只最后一条被执行。
    用法:
    CMD ["executable","param1","param2"]
    CMD ["param1","param2"]
    CMD <command> <param1> <param2>

    7. ENV

    指定一个环境变量,可以被RUN,WORKDIR命令使用,并在容器运行时保持。
    用法:
    ENV <key> <value>
    ENV <key1>=<value1> <k2>=<v2> <k3>=<v3> ...

    8. ENTRYPOINT

    配置容器启动后执行的命令,并且不可被 docker run 提供的参数覆盖,每个Dockerfile中只能有一个 ENTRYPOINT ,当指定多个时,只有最后一个起效。
    用法:
    ENTRYPOINT [“executable”, “param1”, “param2”]
    ENTRYPOINT <command> <param1> <param2>

    9. WORKDIR

    设置工作目录,对RUN,CMD,ENTRYPOINT,COPY,ADD生效。如果不存在则会创建。
    用法:
    WORKDIR <path>

    10. EXPOSE

    功能为暴漏容器运行时的监听端口给外部
    用法:
    EXPOSE <port>

    Dockerfile实践

    通读过上面的Dockerfile命令,相信对编写一个Dockerfile有了一个初步的认识
    接着,我们来通过一个具体的需求,来看一个完整的镜像是怎么通过Dockerfile生成的

    1. 需求

    使用32位的jre环境运行一个dubbo服务的jar包

    2. 编写Dockerfile

    首先,我们需要一个32位的jre环境,你可以从镜像仓库找一个,但此处,我们选择通过Dockerfile自己创建

    # 指定基础镜像
    FROM i386/centos:6
    # 作者信息
    MAINTAINER trainoo "trainoo@163.com"
    # 添加jre环境,add会自动解压
    ADD jre-8u211-linux-i586.tar.gz /opt/docker/java/jre8
    # 设置java环境变量
    ENV JAVA_HOME=/opt/docker/java/jre8/jre1.8.0_211 
    	CLASSPATH=$JAVA_HOME/bin 
    	PATH=.:$JAVA_HOME/bin:$PATH
    # 容器启动后执行,显示java版本号,可以查看环境是否安装成功
    CMD ["java","-version"]
    

    问:为什么使用 i386/centos:6 作为基础镜像?
    答:因为32位的jre当然是使用32位的环境运行比较方便
    如果使用64位的环境运行32位jre也是可以的,但是需要安装如下依赖:
    RUN yum update && yum -y install glibc.i686 zlib.i686 libstdc++.i686
    如果打包的是64位的jre,那么基础镜像可以换成:frolvlad/alpine-glibc

    问:jre-8u211-linux-i586.tar.gz 这个包从哪下载?
    答:你可以从官网下载,当然,你看到此文章时,可能网址已经变化。

    3. 构建

    如上,我们写好了一个Dockerfile,只需把jre包跟Dockerfile放在同一路径
    即可开始构建,命令如下:docker build -t jre8-64:second .
    ps: 此处应该贴32位的运行过程的,但是64位的跟32位没太大区别,所以就这样吧

    [root@xxx jre8-x32]# ll
    total 89060
    -rw-r--r--. 1 root root      369 Jun 27 18:38 Dockerfile
    -rw-r--r--. 1 root root 91192891 Jun 26 14:52 jre-8u211-linux-i586.tar.gz
    
    [root@xxx jre8-x64]# docker build -t jre8-64:second .
    Sending build context to Docker daemon  87.86MB
    Step 1/5 : FROM frolvlad/alpine-glibc:alpine-3.10
     ---> 74b43ef19206
    Step 2/5 : MAINTAINER trainoo "trainoo@163.com"
     ---> Using cache
     ---> 1257f5f17f2a
    Step 3/5 : ADD jre-8u211-linux-x64.tar.gz /opt/docker/java/jre8
     ---> Using cache
     ---> 10692b79be49
    Step 4/5 : ENV JAVA_HOME=/opt/docker/java/jre8/jre1.8.0_211 CLASSPATH=$JAVA_HOME/bin PATH=.:$JAVA_HOME/bin:$PATH
     ---> Running in 1710cc8fd3aa
    Removing intermediate container 1710cc8fd3aa
     ---> 5dd2f0ae922c
    Step 5/5 : CMD ["java","-version"]
     ---> Running in 368238c0940b
    Removing intermediate container 368238c0940b
     ---> e6e9cf729e37
    Successfully built e6e9cf729e37
    Successfully tagged jre8-64:second
    
    [root@xxx jre8-x64]# docker images -f reference=jre8*
    REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
    jre8-64             second              e6e9cf729e37        53 seconds ago      251MB
    jre8-32             base                9035f0dcd0ed        20 hours ago        433MB
    jre8-64             base                ce0823b7fdc3        47 hours ago        251MB
    
    

    由上面的构建步骤可以看出,每运行一个命令,都会产生一个临时镜像,所以为了避免产生多余的临时镜像,我们要尽量的把多个相同指令的的构建步骤,写在同一行里。

    4. 运行项目

    假设我们把项目打包好了,打包好的jar包为:my-service-1.0.jar。

    FROM jre8-32:base
    MAINTAINER trainoo "trainoo@163.com"
    COPY ./jar/ /opt/dubbo-server/
    RUN cd /opt/dubbo-server/ && mv $(ls | grep jar) app.jar
    WORKDIR /opt/dubbo-server/
    CMD ["java","-Xms512M","-Xmx512M","-jar","app.jar"]
    
    // 为了通用性,这里把jar文件(如果不是springboot项目,还有lib等依赖包)放在jar目录下,COPY时一起复制过去
    // 同样目的,使用 mv $(ls | grep jar) app.jar 将需要被执行的jar文件统一命名成 app.jar
    
    # 构建镜像
    [root@xxx jre8-x64]# docker build -t myservice:v1 .
    .....此处省略部分.....
    # 启动容器
    [root@xxx jre8-x64]# docker run -d --name myservice myservice:v1
    # 查看容器
    [root@xxx jre8-x64]# docker ps 
    

    后续总结

    事情总是不会这么顺利,中途总是会有一些小插曲,所以下面是可能遇到的问题的解决方案

    docker 批量删除产生的缓存镜像
    # 第一种风格
    docker ps -a | grep "Exited" | awk '{print $1 }'|xargs docker stop
    docker ps -a | grep "Exited" | awk '{print $1 }'|xargs docker rm
    docker images | grep none | awk '{print $3}' | xargs docker rmi
    
    # 第二种风格
    docker rm $(docker ps -aq -f status=exited)
    docker rmi $(docker images -qa -f reference=*:v1)
    
    container 时区跟 host 不一致
    # Dockerfile中添加
    RUN echo "Asia/Shanghai" > /etc/timezone
    
    # 启动时添加:-v /etc/localtime:/etc/localtime:ro
    docker run -d -v /etc/localtime:/etc/localtime:ro --net mynet --name myservice myservice:v1
    
    docker运行项目,日志中文显示???
    # Dockerfile中添加,指定语言环境
    RUN localedef -i en_US -f UTF-8 en_US.UTF-8
    ENV LANG en_US.UTF-8  
    ENV LANGUAGE en_US:en  
    ENV LC_ALL en_US.UTF-8
    
  • 相关阅读:
    NS3 使用NS3工具PyViz
    ns-3 NetAnim遇到了一个问题
    NS-3 MyFirstScriptExample
    Ubuntu下Eclipse安装与编译ns-3遇见的各种问题
    Ubuntu 12.04 安装JDK
    近期学习的参考博客链接
    Win7上安装WMware虚拟机和Ubuntu操作系统
    C++课程小结 继承与派生
    C语言中生产随机数 rand()函数
    PTA第三次上机
  • 原文地址:https://www.cnblogs.com/Trainoo/p/11108389.html
Copyright © 2011-2022 走看看