zoukankan      html  css  js  c++  java
  • Dockerfile简单实战

    Dockerfile编写教程

    本文大部分内容参考于:https://yeasy.gitbooks.io/docker_practice/image/build.html

    1. 创建一个目录并进入到该目录下创建Dockerfile文件

      vim /root/test/Dockerfile
      
    2. 需要安装的镜像文件

      这里安装了最新版的centos和python3.7.4以及安装过程中所需要的依赖,开放端口为8000端口

      • 初级写法
      FROM    centos:latest
      MAINTAINER  ryan.liu "liuhuan086@gmail.com"
      
      RUN     yum install -y gcc zlib-devel openssl-devel libffi-devel make
      WORKDIR /tmp
      RUN     curl -O https://www.python.org/ftp/python/3.7.4/Python-3.7.4.tgz
      RUN     tar -zxvf Python-3.7.4.tgz
      
      WORKDIR Python-3.7.4
      RUN     mkdir -p /usr/local/python3
      RUN     ./configure --prefix=/usr/local/python3
      RUN     make && make install
      RUN     echo export PATH="/usr/local/python3/bin:$PATH" >> ~/.bashrc
      RUN     source ~/.bashrc
      RUN     /usr/local/python3/bin/pip3 install Django==2.2.3
      RUN     /usr/local/python3/bin/pip3 install pymysql
      WORKDIR /
      EXPOSE  8000
      

      Dockerfile 中每一个指令都会建立一层,RUN 也不例外。每一个 RUN 的行为,就和刚才我们手工建立镜像的过程一样:新建立一层,在其上执行这些命令,执行结束后,commit 这一层的修改,构成新的镜像。

      而上面的这种写法,创建了 7 层镜像。这是完全没有意义的,而且很多运行时不需要的东西,都被装进了镜像里,比如编译环境、更新的软件包等等。结果就是产生非常臃肿、非常多层的镜像,不仅仅增加了构建部署的时间,也很容易出错。 这是很多初学 Docker 的人常犯的一个错误。

      Union FS 是有最大层数限制的,比如 AUFS,曾经是最大不得超过 42 层,现在是不得超过 127 层。

      • 正确写法
      FROM    centos:latest
      MAINTAINER  ryan.liu "liuhuan086@gmail.com"
        
      RUN yum install -y gcc zlib-devel openssl-devel libffi-devel make 
         	&& cd /tmp 
         	&& curl -O https://www.python.org/ftp/python/3.7.4/Python-3.7.4.tgz 
          && tar -zxvf Python-3.7.4.tgz 
          && rm -rf Python-3.7.4.tgz 
          && mkdir -p /usr/local/python3 
          && cd Python-3.7.4 
          && ./configure --prefix=/usr/local/python3 
          && make && make install 
          && echo export PATH="/usr/local/python3/bin:$PATH" >> ~/.bashrc 
          && source ~/.bashrc 
          && /usr/local/python3/bin/pip3 install Django==2.2.3 
          && /usr/local/python3/bin/pip3 install pymysql 
          && cd /
      EXPOSE  8000
      
    3. 执行

      Dockerfile所在目录执行

      docker build -t centos7:latest .
      

      镜像构建上下文(Context)

      如果注意,会看到 docker build 命令最后有一个 .. 表示当前目录,而 Dockerfile 就在当前目录,因此不少初学者以为这个路径是在指定 Dockerfile 所在路径,这么理解其实是不准确的。如果对应上面的命令格式,你可能会发现,这是在指定 上下文路径。那么什么是上下文呢?

      首先我们要理解 docker build 的工作原理。Docker 在运行时分为 Docker 引擎(也就是服务端守护进程)和客户端工具。Docker 的引擎提供了一组 REST API,被称为 Docker Remote API,而如 docker 命令这样的客户端工具,则是通过这组 API 与 Docker 引擎交互,从而完成各种功能。因此,虽然表面上我们好像是在本机执行各种 docker 功能,但实际上,一切都是使用的远程调用形式在服务端(Docker 引擎)完成。也因为这种 C/S 设计,让我们操作远程服务器的 Docker 引擎变得轻而易举。

      当我们进行镜像构建的时候,并非所有定制都会通过 RUN 指令完成,经常会需要将一些本地文件复制进镜像,比如通过 COPY 指令、ADD 指令等。而 docker build 命令构建镜像,其实并非在本地构建,而是在服务端,也就是 Docker 引擎中构建的。那么在这种客户端/服务端的架构中,如何才能让服务端获得本地文件呢?

      这就引入了上下文的概念。当构建的时候,用户会指定构建镜像上下文的路径,docker build 命令得知这个路径后,会将路径下的所有内容打包,然后上传给 Docker 引擎。这样 Docker 引擎收到这个上下文包后,展开就会获得构建镜像所需的一切文件。

      如果在 Dockerfile 中这么写:

      COPY ./package.json /app/
      

      这并不是要复制执行 docker build 命令所在的目录下的 package.json,也不是复制 Dockerfile 所在目录下的 package.json,而是复制 上下文(context) 目录下的 package.json

      因此,COPY 这类指令中的源文件的路径都是相对路径。这也是初学者经常会问的为什么 COPY ../package.json /app 或者 COPY /opt/xxxx /app 无法工作的原因,因为这些路径已经超出了上下文的范围,Docker 引擎无法获得这些位置的文件。如果真的需要那些文件,应该将它们复制到上下文目录中去。

      现在就可以理解刚才的命令 docker build -t nginx:v3 . 中的这个 .,实际上是在指定上下文的目录,docker build 命令会将该目录下的内容打包交给 Docker 引擎以帮助构建镜像。

      如果观察 docker build 输出,我们其实已经看到了这个发送上下文的过程:

      $ docker build -t nginx:v3 .
      Sending build context to Docker daemon 2.048 kB
      ...
      

      理解构建上下文对于镜像构建是很重要的,避免犯一些不应该的错误。比如有些初学者在发现 COPY /opt/xxxx /app 不工作后,于是干脆将 Dockerfile 放到了硬盘根目录去构建,结果发现 docker build 执行后,在发送一个几十 GB 的东西,极为缓慢而且很容易构建失败。那是因为这种做法是在让 docker build 打包整个硬盘,这显然是使用错误。

      一般来说,应该会将 Dockerfile 置于一个空目录下,或者项目根目录下。如果该目录下没有所需文件,那么应该把所需文件复制一份过来。如果目录下有些东西确实不希望构建时传给 Docker 引擎,那么可以用 .gitignore 一样的语法写一个 .dockerignore,该文件是用于剔除不需要作为上下文传递给 Docker 引擎的。

      那么为什么会有人误以为 . 是指定 Dockerfile 所在目录呢?这是因为在默认情况下,如果不额外指定 Dockerfile 的话,会将上下文目录下的名为 Dockerfile 的文件作为 Dockerfile。

      这只是默认行为,实际上 Dockerfile 的文件名并不要求必须为 Dockerfile,而且并不要求必须位于上下文目录中,比如可以用 -f ../Dockerfile.php 参数指定某个文件作为 Dockerfile

      当然,一般大家习惯性的会使用默认的文件名 Dockerfile,以及会将其置于镜像构建上下文目录中。

    4. 查看镜像

      docker images
      
    5. 运行容器

      docker run -it --name=centos7 centos7:latest /bin/bash
      

    其他相关命令

    • 停止运行的容器

      docker stop centos7
      
    • 删除已停止的容器

      docker rm centos7
      
    • 查看所有已下载镜像

      docker images
      
  • 相关阅读:
    Allegro PCB Design GXL (legacy) 使用slide无法将走线推挤到焊盘的原因
    OrCAD Capture CIS 16.6 导出BOM
    Altium Designer (17.0) 打印输出指定的层
    Allegro PCB Design GXL (legacy) 将指定的层导出为DXF
    Allegro PCB Design GXL (legacy) 设置十字大光标
    Allegro PCB Design GXL (legacy) 手动更改元器件引脚的网络
    magento产品导入时需要注意的事项
    magento url rewrite
    验证台湾同胞身份证信息
    IE8对css文件的限制
  • 原文地址:https://www.cnblogs.com/liuhuan086/p/14716524.html
Copyright © 2011-2022 走看看