ethan

读完需要

11分钟

速读仅需 4 分钟

/ 使用 Dockerfile 定制镜像 /

什么是 Dockerfile 呢?

Dockerfile 是一个文本文档,其中包含用户可以在命令行上调用以组装映像的所有命令。Docker 可以通过阅读该文件中的指令来自动构建映像。(类似于 Linux 上的 bash 脚本,Docker 通过该脚本构建镜像)

1

使用 dockerfile 制作一个 nginx 镜像

$ mkdir mynginx$ cd mynginx$ touch Dockerfile   //首字母必须大写

Dockerfile 文件内容如下

FROM nginxRUN echo '

Hello, Docker!

' > /usr/share/nginx/html/index.html

这个 Dockerfile 很简单,一共就两行。涉及到了两条指令,FROM 和 RUN。

1.1

FROM

功能:指定基础镜像

所谓定制镜像,那一定是以一个镜像为基础,在其上进行定制。就像我们之前运行了一个 nginx 镜像的容器,再进行修改一样,基础镜像是必须指定的。而 FROM 就是指定 基础镜像,因此一个 Dockerfile 中 FROM 是必备的指令,并且必须是第一条指令。

一般使用中我们通过 Docker Hub ( https://hub.docker.com/search?q=&type=image&image_filter=official ) 来查找相关镜像。如下图所示,红标中标识的为官方镜像

除了选择现有镜像为基础镜像外,Docker 还存在一个特殊的镜像,名为 scratch(该镜像不能通过 docker pull 命令直接拉取)。这个镜像是虚拟的概念,并不实际存在,它表示一个空白的镜像。

因为本人只对 PHP 较为熟悉,没有使用过 go,这个也不是很了解,就先跳过了

1.2

RUN

功能:执行命令

用来执行命令行命令的

实际使用下有两种格式

  1. shell 格式:

    RUN 
  2. exec 格式:

    RUN ["可执行文件", "参数1", "参数2"]

Dockerfile 中每一个指令都会建立一层,RUN 也不例外。每一个 RUN 执行结束后,都会 commit 这一层的修改,构成新的镜像。所以在使用中尽力减少指令。

FROM debian:stretchRUN apt-get updateRUN apt-get install -y gcc libc6-dev make wgetRUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"RUN mkdir -p /usr/src/redisRUN tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1RUN make -C /usr/src/redisRUN make -C /usr/src/redis install

上面的这种写法,创建了 7 层镜像。这是完全没有意义的,而且很多运行时不需要的东西,都被装进了镜像里,比如编译环境、更新的软件包等等。结果就是产生非常臃肿、非常多层的镜像,不仅仅增加了构建部署的时间,也很容易出错。我们在以后的使用应该避免。正确的写法如下所示:

FROM debian:stretchRUN buildDeps='gcc libc6-dev make wget' \    && apt-get update \    && apt-get install -y $buildDeps \    && wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \    && mkdir -p /usr/src/redis \    && tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \    && make -C /usr/src/redis \    && make -C /usr/src/redis install \    && rm -rf /var/lib/apt/lists/* \    && rm redis.tar.gz \    && rm -r /usr/src/redis \    && apt-get purge -y --auto-remove $buildDeps

在上一个 Dockerfile 中所有的命令只有一个目的,就是编译、安装 redis 可执行文件。因此没有必要建立很多层,这只是一层的事情。因此,这里我们仅仅使用一个 RUN 指令,并使用 && 将各个所需命令串联起来。将之前的 7 层,简化为了 1 层。

在撰写 Dockerfile 的时候,要经常提醒自己,这并不是在写 Shell 脚本,而是在定义每一层该如何构建。

2

构建

命令格式:

docker build [选项] 
$ docker build -t mynginx:v1 .Sending build context to Docker daemon  2.048kBStep 1/2 : FROM nginx ---> 08393e824c32Step 2/2 : RUN echo '

Hello, Docker!

' > /usr/share/nginx/html/index.html ---> Running in 1d7edd724b5fRemoving intermediate container 1d7edd724b5f ---> e29ba82c8e43Successfully built e29ba82c8e43Successfully tagged mynginx:v1// 查看刚刚创建的镜像$ docker image lsREPOSITORY TAG IMAGE ID CREATED SIZEmynginx v1 e29ba82c8e43 3 minutes ago 132MB

  1. -t 表示指定镜像的名称和标签,格式为 name:tag

  2. 最后有个点,表示构建的上下文路径为当前目录

3

其他构建方式

  1. 通过 Git repo 进行构建

  2. 使用 tar 包进行构建

4

常用指令介绍

COPY 复制文件

格式:

  • COPY [--chown=:]  

    (常用)

  • COPY [--chown=:] ["", ""]

构建上下文目录中 的文件/目录复制到新的一层的镜像内的 位置。

COPY package.json /usr/src/app/

加上 --chown=:选项来改变文件的所属用户及所属组

COPY --chown=55:mygroup files* /mydir/COPY --chown=bin files* /mydir/COPY --chown=1 files* /mydir/COPY --chown=10:11 files* /mydir/

ADD 更高级的复制

和 COPY 的格式和性质基本一致。但是在 COPY 基础上增加了一些功能。

  • 可以是一个 URL。Docker 引擎会试图去下载这个链接的文件放到 去。下载后的文件权限自动设置为 600

  • 为一个 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,ADD 指令将会自动解压缩这个压缩文件到 去。

在 Docker 官方的 Dockerfile 最佳实践文档 中要求,尽可能的使用 COPY,因为 COPY 的语义很明确,就是复制文件而已,而 ADD 则包含了更复杂的功能,其行为也不一定很清晰。最适合使用 ADD 的场合,就是所提及的需要自动解压缩的场合。

CMD 容器启动命令

Docker 不是虚拟机,容器就是进程。既然是进程,那么在启动容器的时候,需要指定所运行的程序及参数。CMD 指令就是用于指定默认的容器主进程的启动命令的。

格式:

  • shell 格式:CMD

  • exec 格式:CMD ["可执行文件", "参数 1", "参数 2"...] (推荐,一定要使用双引号)

ENV 设置环境变量

用于设置环境变量,无论是后面的其它指令,如 RUN,还是运行时的应用,都可以直接使用这里定义的环境变量。

格式:

  • ENV

  • ENV

    ==...

ARG 构建参数

格式:

  • ARG [=]

与 ENV 指令一样,都是设置环境变量。所不同的是,ARG 所设置的构建环境的环境变量,在将来容器运行时是不会存在这些环境变量的。

Dockerfile 中的 ARG 指令是定义参数名称,以及定义其默认值。该默认值可以在构建命令 docker build 中用

--build-arg =

来覆盖。

VOLUME 定义匿名卷

格式:

  • VOLUME ["", ""...]
  • VOLUME 

示例:

容器中的 /data 目录自动挂载到匿名卷中

VOLUME /data

该指令可以在运行时被覆盖

docker run -d -v mydata:/data xxxx

EXPOSE 暴露端口

格式:

  • EXPOSE  [...]

声明运行时容器提供服务端口,这只是一个声明,在运行时并不会因为这个声明就会开启这个端口的服务。

写入这样的声明有两个好处,一个是帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射;另一个用处则是在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口。

WORKDIR 指定工作目录

格式:

  • WORKDIR 。

使用 WORKDIR 指令可以来指定工作目录(或者称为当前目录),以后各层的当前目录就被改为指定的目录,如该目录不存在,WORKDIR 会帮你建立目录。

RUN cd /appRUN echo "hello" > world.txt

使用上面的内容构建镜像后会发现根本找不到

/app/world.txt

文件。原因其实很简单,在 Shell 中,连续两行是同一个进程执行环境,因此前一个命令修改的内存状态,会直接影响后一个命令;而在 Dockerfile 中,这两行 RUN 命令的执行环境根本不同,是两个完全不同的容器。这就是对 Dockerfile 构建分层存储的概念不了解所导致的错误。

因此如果需要改变以后各层的工作目录的位置,那么应该使用 WORKDIR 指令。

USER 指定当前用户

格式:

  • USER [:]

USER 指令和 WORKDIR 相似,都是改变环境状态并影响以后的层。WORKDIR 是改变工作目录,USER 则是改变之后层的执行 RUN, CMD 以及 ENTRYPOINT 这类命令的身份。当然,和 WORKDIR 一样,USER 只是帮助你切换到指定用户而已,这个用户必须是事先建立好的,否则无法切换。

其他指令参考官方文档

docker安装redis提示没有日记写入权限_Docker 学习笔记(第六集:使用 Dockerfile 定制镜像)...相关推荐

  1. docker安装redis提示没有日记写入权限_浅析Linux下Redis的攻击面(一)

    文章转自先知社区:https://xz.aliyun.com/t/7974 0x0 前言   Redis在内网渗透中常常扮演着重要的角色,其攻击方式非常多样化,在内网复杂的环境架构中容易出现各种问题, ...

  2. docker安装redis提示没有日记写入权限_对 Redis 在 Windows 下的利用方式思考

    我写的文章永远都是那么的又臭又长又菜. 前言 上次写了一篇有关 SSRF 打 Redis 主从的文章,居然被人喷了!!!说我根本就没有复现过张嘴就来???我没有理会,然后又有朋友在群问,Redis 在 ...

  3. 史上最详细Docker安装Redis (含每一步的图解)实战

    不仅教你安装,还教你删除. 每一行命令都带图解,绝对能懂. 大家对搭建Redis Clustr (Redis 集群)感兴趣的,可以看看这篇文章 Docker搭建Redis Cluster集群环境 希望 ...

  4. 深入学习 Redis 之第 1 篇 —— Docker 安装 Redis 并搭建主从复制集群

    环境要求:CentOS7 X64 位,Redis6.0+ 理论基础 1.什么是 Redis 的主从复制? Redis 的复制功能支持多个库之间的数据同步.一类是主库(master),另一类是从库(sl ...

  5. Docker系列 六. Docker 安装 Redis

    Docker 安装 Redis Redis 是一个开源的使用 ANSI C 语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value 的 NoSQL 数据库,并提供多种语言的 API . ...

  6. Docker 安装 Redis

    Docker 安装 Redis 方法一.docker pull redis:3.2 查找 Docker Hub上的 redis 镜像: docker search redis 这里我们拉取官方的镜像, ...

  7. Docker 安装redis(四)

    Docker 安装redis 1.搜索docker镜像(可以看到搜索的结果,这个结果是按照一定的星级评价规则排序的) docker search redis 2.拉取docker的mysql镜像(如果 ...

  8. docker 安装redis第三方集群方案 codis

    docker 安装redis第三方集群方案 codis docker 安装redis第三方集群方案 codis 首先,安装好docker环境,这里不提,需要看的可以在我的博客里找, 事先准备好zook ...

  9. docker 安装redis 挂载到宿主机

    1.首先去redis获取对应版本的配置文件redis.conf:  http://download.redis.io/releases/ 我选择的是 6.0.9 解压以后 有一个redis.conf ...

最新文章

  1. 【转】【C++】__stdcall、__cdcel和__fastcall三者的区别
  2. python里res有什么用_python – 为什么在tensorflow中构建resnet模型时使用固定填充...
  3. linux版本wannacry,Wannacry勒索软件解决方案
  4. 无法打开包括文件:“mysql..h”: No such file or directory
  5. 实践平台linux,关于构造Linux系统实践平台的设想
  6. 手动创建Oracle实例
  7. 【EMV L2】数据元格式 对齐方式
  8. 终于有人把项目搭建讲明白了!
  9. [SCM]源码管理 - SVN Server
  10. YII与Ace Admin 的集成
  11. Flink 在米哈游的落地实践
  12. 分享一下防水拉线位移编码器的原理及选型
  13. linux光盘引导项,Linux制作grub引导光盘
  14. H5canvas(保存图片,globalCompositeOperation)
  15. 教你熟透开关电源设计的各种元器件
  16. 解决微信上下滑动出现黑底背景问题
  17. 知识蒸馏 | (1) 知识蒸馏概述
  18. 微信的常用设备 只能看到android,安卓手机撤回的微信图片可以查看啦,赶紧学起来...
  19. Sigma Designs SMP8910媒体处理器的3DTV、蓝光和OTT体验
  20. html怎么调颜色的饱和度,css – LESS:色调,饱和度和亮度 – 如何使用?

热门文章

  1. Android — 长按ListView 利用上下文菜单(ActionMode) 进行批量事件处理
  2. HP存储raid5两块硬盘离线lvm下vxfs文件系统恢复数据过程
  3. Thread系列——Thread.Sleep(0)
  4. 基于Linux(LAMP)平台搭建MYsql数据库(二)
  5. 某程序员求助:30万年包留在家乡华为,50万年包去新加坡shopee,选哪个?
  6. 不会一致性hash算法,劝你简历别写搞过负载均衡
  7. 美团智能问答技术探索与实践
  8. 面试前必知必会的二分查找及其变种
  9. 无异常日志,就不能排查问题了???
  10. 不满你说,我最近跟Java源码杠上了...