zoukankan      html  css  js  c++  java
  • docker--Dockerfile

    前戏

    镜像是容器的基础,每次执行docker run的时候都会指定哪个镜像作为容器运行的基础,我们之前的例子都是使用来自docker hub的镜像。直接使用这些镜像只能满足一定的需求,当镜像无法满足我们的需求时,就得自定制这些镜像。

    镜像的定制就是定制每一层所添加的配置、文件。如果把每一层修改,安装,构建,操作的命令都写入到一个脚本,用脚本来构建、定制镜像,这个脚本就是Dockerfile。

    Dockerfile是一个文本文件,其内部包含一条条指令, 每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建

    Dockerfile的命令

    FROM scratch #制作base image 基础镜像,尽量使用官方的image作为base image
    FROM centos # 使用base image
    FROM ubuntu:14.04 #带有tag的base image
    
    LABEL version=“1.0” #容器元信息,帮助信息,Metadata,类似于代码注释
    LABEL maintainer=“zouzou0214"
    
    #对于复杂的RUN命令,避免无用的分层,多条命令用反斜线换行,合成一条命令!
    RUN yum update && yum install -y vim 
        Python-dev #反斜线换行
    RUN /bin/bash -c "source $HOME/.bashrc;echo $HOME”
    
    WORKDIR /root #相当于linux的cd命令,改变目录,尽量使用绝对路径!!!不要用RUN cd
    WORKDIR /test # 如果没有就自动创建
    WORKDIR demo # 再进入demo文件夹
    RUN pwd     #打印结果是/test/demo
    
    ADD and COPY 
    ADD hello /  #把本地文件添加到镜像中(和Dockerfile同级),把本地的hello可执行文件拷贝到镜像的/目录
    ADD test.tar.gz /  #添加到根目录并解压
    
    WORKDIR /root
    ADD hello test/  #进入/root/ 添加hello可执行命令到test目录下,也就是/root/test/hello 一个绝对路径
    COPY hello test/  #等同于上述ADD效果
    '''
    ADD与COPY
       - 优先使用COPY命令
        -ADD除了COPY功能还有解压功能
    添加远程文件/目录使用curl或wget
    '''
    
    ENV #环境变量,尽可能使用ENV增加可维护性
    ENV MYSQL_VERSION 5.6 #设置一个mysql常量
    RUN yum install -y mysql-server=“${MYSQL_VERSION}” 
    
    ------这里需要稍微理解一下了-------中级知识---
    
    VOLUME and EXPOSE 
    存储和网络
    
    RUN and CMD and ENTRYPOINT
    RUN:执行命令并创建新的Image Layer
    CMD:设置容器启动后默认执行的命令和参数
    ENTRYPOINT:设置容器启动时运行的命令
    
    Shell格式和Exec格式
    RUN yum install -y vim
    CMD echo ”hello docker”
    ENTRYPOINT echo “hello docker”
    
    Exec格式
    RUN [“apt-get”,”install”,”-y”,”vim”]
    CMD [“/bin/echo”,”hello docker”]
    ENTRYPOINT [“/bin/echo”,”hello docker”]
    
    
    通过shell格式去运行命令,会读取$name指令,而exec格式是仅仅的执行一个命令,而不是shell指令
    cat Dockerfile
        FROM centos
        ENV name Docker
        ENTRYPOINT [“/bin/echo”,”hello $name”]#这个仅仅是执行echo命令,读取不了shell变量
        ENTRYPOINT  [“/bin/bash”,”-c”,”echo hello $name"]
    
    CMD
    容器启动时默认执行的命令
    如果docker run指定了其他命令(docker run -it [image] /bin/bash ),CMD命令被忽略
    如果定义多个CMD,只有最后一个执行
    
    ENTRYPOINT
    让容器以应用程序或服务形式运行
    不会被忽略,一定会执行
    最佳实践:写一个shell脚本作为entrypoint
    COPY docker-entrypoint.sh /usr/local/bin
    ENTRYPOINT [“docker-entrypoint.sh]
    EXPOSE 27017
    CMD [“mongod”]
    
    [root@master home]# more Dockerfile
    FROm centos
    ENV name Docker
    #CMD ["/bin/bash","-c","echo hello $name"]
    ENTRYPOINT ["/bin/bash","-c","echo hello $name”]

    创建自己的容器镜像

    1.先准备一段flask代码

    myflask.py

    from flask import Flask
        app=Flask(__name__)
        @app.route('/')
        def hello():
            return "hello docker,i am is zouzou"
        if __name__=="__main__":
            app.run(host='0.0.0.0',port=8080)

    2.准备传到docker容器里的文件

    [root@HH tmp]# ls
    CentOS-Base.repo  Dockerfile  epel.repo  myflask.py

    3.制作Dockerfile

    FROM centos
    LABEL maintainer="zouzou0214"
    ADD CentOS-Base.repo /etc/yum.repos.d/
    ADD epel.repo /etc/yum.repos.d/
    RUN yum clean all
    RUN yum install python-pip -y
    RUN pip install -i https://pypi.tuna.tsinghua.edu.cn/simple flask
    COPY myflask.py /app/
    WORKDIR /app/
    EXPOSE 8081
    CMD ["python","myflask.py"]
    • 1.引入一个centos镜像,为基础镜像
    • 2.作者注释信息
    • 3.添加本地的两个yum文件,到容器的/etc/yum.repos.d/底下
    • 4.清空yum缓存
    • 5.yum安装pip工具
    • 6.pip安装flask模块,指定清华源
    • 7.拷贝本地的flask代码,到容器的/app/目录下
    • 8.切换工作目录,到/app底下
    • 9.暴露容器的8081端口,然后在运行镜像时候,加上-p参数,指定端口映射
    • 10.执行命令,运行flask

    4.构建docker镜像

    docker build -t zouzu0214/my-docker-flask .

    注意:最后面有个.(点)代表从当前目录build

    构建当前目录的Dcokerfile,然后构建出一个名为yuchao163/s14-flask-docker 这个的镜像文件

    -t tag参数,给镜像加上标记名

    dockerhub账户名:zouzou0214,dockerhub账户名/镜像名 ,是为了后面讲docker镜像,推送到dockerhub

    5.查看镜像是否构建成功:docker images

    [root@HH tmp]# docker images
    REPOSITORY                  TAG                 IMAGE ID            CREATED             SIZE
    zouzu0214/my-docker-flask   latest              845652a3022e        12 seconds ago      346MB
    centos                      latest              67fa590cfc1c        5 weeks ago         202MB

    我本地是没有centos镜像的,会去先下载一个centos镜像,然后基于该镜像构建

    6.运行镜像

    [root@HH tmp]# docker run -d -p 9000:8081 8456
    bcd4e98ba419f5eaf3c9f43e64d9b1dd2558fddb2316be84b46fdf656318ab64

    docker run -p 9000:8081 -d 8456

    -p 映射9000端口到容器的8081

    -d 后台运行

    8456  镜像id

    7.查看已经运行的docker实例

    [root@HH tmp]# docker ps
    CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                               NAMES
    44a53f62f533        76a7                "/sbin/tini -- /usr/…"   11 hours ago        Up 11 hours         50000/tcp, 0.0.0.0:8000->8080/tcp   MyJenkins

    RUN、CMD、ENTRYPOINT之间的区别

    这三个命令都是执行命令的,那它们之间有什么区别呢?先来熟悉两个概念

    • shell命令格式:RUN yum install -y python
    • exec命令格式:RUN [ "yum","install" ,"-y" ,"python"]

    我们有一个centos:7的基础镜像

    案例一:写一个dockerfile,内容如下

    FROM centos:7
    RUN echo "my is run..."
    CMD ["echo","my","is","cmd"]
    ENTRYPOINT ["echo","my","is","entrypoint"]

    构建镜像

    docker build -t centos:v1 .

     启动这个镜像

    [root@WC ~]# docker run centos:v1
    my is entrypoint echo my is cmd

    由上面的例子我们可以看出来,RUN 命令是作用于镜像的,而CMD和ENTRYPOINT是作用于容器的,在容器启动时执行的,并且先执行ENTRYPOINT在执行CMD

    案例二:修改dockerfile,修改后的如下

    FROM centos:7
    CMD ["echo","my","is","cmd1"]
    CMD ["echo","my","is","cmd2"]
    ENTRYPOINT ["echo","my","is","entrypoint1"]
    ENTRYPOINT ["echo","my","is","entrypoint2"]

    构建镜像

    [root@WC ~]# docker build -t centos:v2 .
    Sending build context to Docker daemon    854kB
    Step 1/5 : FROM centos:7
     ---> 5e35e350aded
    Step 2/5 : CMD ["echo","my","is","cmd1"]
     ---> Running in a5a50c279343
    Removing intermediate container a5a50c279343
     ---> 580f6c1ca1d8
    Step 3/5 : CMD ["echo","my","is","cmd2"]
     ---> Running in bda45cc4de5f
    Removing intermediate container bda45cc4de5f
     ---> 98daa774b962
    Step 4/5 : ENTRYPOINT ["echo","my","is","entrypoint1"]
     ---> Running in f181f49673e7
    Removing intermediate container f181f49673e7
     ---> f477e3841a4a
    Step 5/5 : ENTRYPOINT ["echo","my","is","entrypoint2"]
     ---> Running in cc4b61298119
    Removing intermediate container cc4b61298119
     ---> c7f3fbb0365a
    Successfully built c7f3fbb0365a
    Successfully tagged centos:v2

    还是没有执行CMD和ENTRYPOINT,启动容器

    [root@WC ~]# docker run centos:v2
    my is entrypoint2 echo my is cmd2

    结果:有多个CMD和ENTRYPOINT时,只执行最后的一个

    案例三:修改dockerfile,修改后的如下

    FROM centos:7
    CMD ["-ef"]
    ENTRYPOINT ["ps"]

    构建镜像

    [root@WC ~]# docker build -t centos:v3 .
    Sending build context to Docker daemon  854.5kB
    Step 1/3 : FROM centos:7
     ---> 5e35e350aded
    Step 2/3 : CMD ["-ef"]
     ---> Running in 3c10444a83a0
    Removing intermediate container 3c10444a83a0
     ---> 36d8da189295
    Step 3/3 : ENTRYPOINT ["ps"]
     ---> Running in e7751f2f9c64
    Removing intermediate container e7751f2f9c64
     ---> ba96ea2aebf5
    Successfully built ba96ea2aebf5
    Successfully tagged centos:v3

    启动镜像

     可以看出会将ENTRYPOINT和CMD的执行结果显示出来,我们还可以在启动容器的时候加上参数,会替换掉CMD的参数

    总结:

    • RUN:在构建镜像的时候执行,作用于镜像层面
    • ENTRYPOINT:在容器启动的时候执行,作用于容器层,dockerfile里有多条时只允许执行最后一条,先执行ENTRYPOINT在执行CMD
    • CMD:在容器启动的时候执行,作用于容器层,dockerfile里有多条时只允许执行最后一条,容器启动后执行默认的命令或者参数,允许被修改

    注意:如果ENTRYPOINT使用的是exec的格式,则会将CMD当做参数,如果是shell,则不会将CMD当做参数

  • 相关阅读:
    框架学习之Spring 前言
    XML学习第二节 DTD介绍
    JavaScript重学 V512视频
    框架学习之Spring 第五节 SSH整合开发[Spring2.5+Hibernate3.3+Struts2]
    XML学习第一节 XML简介
    框架学习之Spring 第四节 Spring集成JDBC组件开发
    歌曲:酒干倘卖无 背后的故事
    又要被学校开除了!
    linux常用命令
    心情
  • 原文地址:https://www.cnblogs.com/zouzou-busy/p/11610202.html
Copyright © 2011-2022 走看看