当前位置: 首页 > news >正文

Docker 笔记(2):Dockerfile

Dockerfile是由一系列命令和参数构成的脚本,这些命令应用于基础镜像并最终创建一个新的镜像。

常用的选项

例子:

FROM node:latest
MAINTAINER my_name
ADD ./my_project /code
VOLUME ["/data1", "/data2"]
WORKDIR /code
RUN apt-get install mysql
EXPOSE 6777
ENV SRC_URL www.xxxxxxxxxxx.com/xxxxxxx
RUN wget $SRC_URL
CMD ["node","bin/www"]
  • FROM: 指定基础镜像,如果本地不存在基础镜像,会自动从远程仓库拉取。FROM必须是Dockerfile中除了注释外的第一行语句。
  • MAINTAINER: 用于指定镜像的构建者,当发现坑的时候可以找他
  • ADD: 将本机的文件或目录复制到镜像的某个目录下,在后续的构建命令和容器运行中可以在容器中访问该目录
  • WORKDIR: 指定后续的构建命令的工作路径
  • RUN: 在镜像中运行某条命令,如安装相关的依赖库
  • CMD:用于指定镜像运行时的第一条命令。CMD只能出现一次,如果出现多次,前面的会被覆盖
    CMD ["executable","param1","param2"] 使用 exec 执行,推荐方式;

    CMD command param1 param2 在 /bin/sh 中执行,提供给需要交互的应用;

    CMD ["param1","param2"] 提供给 ENTRYPOINT 的默认参数;
  • EXPOSE:暴露容器的端口,其他容器可以通过该端口访问本容器提供的服务,前提是这些容器在同一个网络中,例子中暴露了6777端口
  • ENV: 设置环境变量。这些环境变量可以在后续的构建命令中使用,当运行容器时,也可以在容器中使用这些变量
  • COPY: 将本机的文件或目录复制到镜像的某个目录下,在后续的构建命令和容器运行中可以在容器中访问该目录。该命令作用同ADD,只是ADD更加强大,如:当拷贝的是压缩包,ADD会自动解压
  • ENTRYPOINT: 容器启动后执行的命令。每个 Dockerfile 中只能有一个ENTRYPOINT,当指定多个时,只有最后一个生效。(CMD指令指定的容器启动时命令可以被docker run指定的命令覆盖;而ENTRYPOINT指令指定的命令不能被覆盖,而是将docker run指定的参数当做ENTRYPOINT指定命令的参数。)
    ENTRYPOINT ["executable", "param1", "param2"]

    ENTRYPOINT command param1 param2(shell中执行)
  • VOLUME: 容器卷是一个可供一个或多个容器使用的特殊目录,它绕过 UFS,将主机目录挂在到容器里面,可以提供很多有用的特性:

    • 数据卷 可以在容器之间共享和重用
    • 对 数据卷 的修改会立马生效
    • 对 数据卷 的更新,不会影响镜像
    • 数据卷 默认会一直存在,即使容器被删除,除非在删除容器的时候使用-v选项: docker rm -v container_id/container_name
    • 注意: 数据卷 的使用,类似于 Linux 下对目录或文件进行 mount,镜像中的被指定为挂载点的目录中的文件会隐藏掉,能显示看的是挂载的 数据卷 。因此你的容器目录dir有一个文件为temp.data,如果你在dir挂载了一个数据卷
    • 在Dockerfile中,无法指定主机上对应的目录

,那么你就再也不能读取temp.data,除非你移除该数据卷。

其他选项

USER

格式:

 USER <用户名>

USER 指令和 WORKDIR 相似,都是改变环境状态并影响以后的层。 WORKDIR 是改变工作目录, USER 则是改变之后层的执行 RUN , CMD 以及 ENTRYPOINT 这类命令的身份。

当然,和 WORKDIR 一样, USER 只是帮助你切换到指定用户而已,这个用户必须是事先建立好的,否则无法切换。

RUN groupadd -r redis && useradd -r -g redis redis
USER redis
RUN [ "redis-server" ]

如果以 root 执行的脚本,在执行期间希望改变身份,比如希望以某个已经建立好的用户来运行某个服务进程,不要使用 su 或者 sudo ,这些都需要比较麻烦的配置,而且在 TTY 缺失的环境下经常出错。建议使用 gosu 。

# 建立 redis 用户,并使用 gosu 换另一个用户执行命令
RUN groupadd -r redis && useradd -r -g redis redis
# 下载 gosu
RUN wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/1.7/
gosu-amd64" \
&& chmod +x /usr/local/bin/gosu \
&& gosu nobody true
# 设置 CMD,并以另外的用户执行
CMD [ "exec", "gosu", "redis", "redis-server" ]

ONBUILD

格式: ONBUILD <其它指令> 。

ONBUILD 是一个特殊的指令,它后面跟的是其它指令,比如 RUN , COPY 等,而这些指令,在当前镜像构建时并不会被执行。只有当以当前镜像为基础镜像,去构建下一级镜像的时候才会被执行。

Dockerfile 中的其它指令都是为了定制当前镜像而准备的,唯有 ONBUILD 是为了帮助别人定制自己而准备的。

fundamental/Dockerfile

FROM node:slim
RUN mkdir /app
WORKDIR /app
ONBUILD COPY ./package.json /app
ONBUILD RUN [ "npm", "install" ]
ONBUILD COPY . /app/
CMD [ "npm", "start" ]

project1/Dockerfile

FROM fundamental
do other thing

在构建 project1 的时候 ONBUILD的命令才会生效。

例子

我们将基于官方的python镜像,搭建一个后端的环境镜像(需要用的库含redis、flask等)。

FROM python:3.6-alpine
# 复制代码到镜像
ADD the_path_of_project /code   
# 设置后面的命令的pwd
WORKDIR /code
# 安装依赖
RUN pip install redis flask
# 运行服务的命令
CMD ["python", "app.py"]

例子中:

  • FROM:指定基础镜像为python:3.6-alpine
  • ADD:项目代码被复制到容器的code目录下
  • WORKDIR:指定后续命令的pwd为code
  • RUN:安装依赖库
  • CMD:指定启动容器时需要运行的命令,即启动我们的项目

参考

  • docker pratice

  • 上一节:Docker 笔记(1):介绍、镜像、容器及其基本操作
  • 下一节:Docker 笔记(3):docker-compose

相关文章:

  • promise原理就是这么简单
  • EXE文件执行过程中发生了什么?
  • MathExam小学一二年级计算题生成器V1.0
  • 建设银行无人银行开业,铁饭碗是属于程序员的
  • Java 集合系列-第八篇-Map架构
  • Redhat7.0下部署NFS服务器
  • 网络,NFS
  • 服务器目录权限
  • LAMP搭建
  • 自动生成指定特征的数独题目(未完待续)
  • 学习python必备的学习网站
  • Linux服务器性能评估
  • Synchronized与Lock的底层实现解析
  • ES6数组的扩展----Array.from()和Array.of()
  • jdk动态代理和cglib动态代理的区别
  • [Vue CLI 3] 配置解析之 css.extract
  • 【162天】黑马程序员27天视频学习笔记【Day02-上】
  • 【css3】浏览器内核及其兼容性
  • 08.Android之View事件问题
  • css选择器
  • happypack两次报错的问题
  • Java,console输出实时的转向GUI textbox
  • Lsb图片隐写
  • Nacos系列:Nacos的Java SDK使用
  • nginx 配置多 域名 + 多 https
  • Python代码面试必读 - Data Structures and Algorithms in Python
  • react 代码优化(一) ——事件处理
  • vue-loader 源码解析系列之 selector
  • 包装类对象
  • 仿天猫超市收藏抛物线动画工具库
  • 将回调地狱按在地上摩擦的Promise
  • 每天10道Java面试题,跟我走,offer有!
  • 前端每日实战:70# 视频演示如何用纯 CSS 创作一只徘徊的果冻怪兽
  • 实战|智能家居行业移动应用性能分析
  • No resource identifier found for attribute,RxJava之zip操作符
  • 2017年360最后一道编程题
  • CMake 入门1/5:基于阿里云 ECS搭建体验环境
  • ionic入门之数据绑定显示-1
  • Play Store发现SimBad恶意软件,1.5亿Android用户成受害者 ...
  • #Linux(权限管理)
  • #我与Java虚拟机的故事#连载10: 如何在阿里、腾讯、百度、及字节跳动等公司面试中脱颖而出...
  • (06)金属布线——为半导体注入生命的连接
  • (2.2w字)前端单元测试之Jest详解篇
  • (ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY)讲解
  • (一)基于IDEA的JAVA基础1
  • (转) ns2/nam与nam实现相关的文件
  • (转)c++ std::pair 与 std::make
  • (转载)跟我一起学习VIM - The Life Changing Editor
  • .bat文件调用java类的main方法
  • .NET Framework .NET Core与 .NET 的区别
  • .Net转前端开发-启航篇,如何定制博客园主题
  • @property python知乎_Python3基础之:property
  • @Repository 注解
  • @Resource和@Autowired的区别
  • [ Linux 长征路第五篇 ] make/Makefile Linux项目自动化创建工具