专栏首页运维录如何使用 Dockerfile自定义镜像?

如何使用 Dockerfile自定义镜像?

之前在隔壁专题(公众号出门左转 Nginx专题) 推送过一篇文章 Nginx 缓存服务器(番外)定制Docker镜像

我们将 ngx_cache_purge模块添加到自定义的 Nginx镜像中,避免每次创建容器后再次安装模块这个繁琐的步骤。

今天使用一个 Java项目的示例,介绍下如何使用 Dockerfile 创建一个自定义Java镜像,以及在 Dockerfile 中常用的一些指令。

环境描述

容器镜像: openjdk:8-jre
容器系统: debian 8 (jessie)
Docker主机: Ubuntu Server 16.04
CI工具: Jenkins & Maven
项目程序: 编译好的 bms.jar 包

操作步骤

1. 准备 Dockerfile

cat bms/Dockerfile

# bms
FROM openjdk:8-jre
MAINTAINER dongnan

# apt
COPY conf/sources.list /etc/apt/sources.list
RUN apt-get update && apt-get install -y \
        wkhtmltopdf xvfb \
        && apt-get clean && rm -r /var/lib/apt/lists/*

# env
ENV TZ=Asia/Shanghai \
    LANG=C.UTF-8

# package
COPY src/bms.jar /root/bms.jar

# workdir
WORKDIR /root/

# statement Port
EXPOSE 8080

# cmd
CMD ["java","-jar","/root/bms.jar"]

2. 构建镜像

守护进程读取 Dockerfile 文件然后按照文件中的指令顺序执行。构建镜像时会一层层构建,前一层是后一层的基础,每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。

docker build -t bms:0.0.1 .
Sending build context to Docker daemon 2.048 mb
# 省略....
Successfully built cd34135ed904

注意: docker build 命令最后有一个. 表示当前目录,而 Dockerfile 就在当前目录,是在指定上下文路径

3. 验证镜像

尝试使用这个镜像创建一个容器,如果容器正常运行说明构建成功。

docker run --name test -tid bms:0.0.1

镜像使用的是分层存储容器也是如此,每个容器运行时是以镜像为基础层,在其上创建一个当前容器的存储层。

容器运行后修改了容器内的文件,也就是改动了容器的存储层,通过 docker diff 命令看到具体的改动。

docker container diff test
C /root         # C 改变
A /root/logs    # A 添加
A /root/logs/bms.log
C /tmp
A /tmp/tomcat-docbase.1383167136.9290

4. 命令帮助

docker build --help

Dockerfile 常用指令

Dockerfile 中每一个指令都会建立一层,上面的示例创建了9层镜像。

FROM: 用于指定基础镜像,一个有效的 Dockerfile 必须使用 FROM做第一个指令。
MAINTAINER: 用于设置作者信息。
RUN: 是用来执行命令的,并将结果提交到当前镜像层。
ENV: 设置环境变量,无论是后面的其它指令,还是运行时的容器,都可以直接使用这个环境变量。
COPY: 将从构建上下文目录中 <源> 文件/目录复制到新的一层的镜像内的 <目标> 位置。
ADD: 与 `COPY` 指令功能基本一致。但是在 COPY 基础上增加了一些功能,例如 ADD会做自动解压工作。
WORKDIR: 用来指定工作目录(**当前目录**),如该目录不存在则会帮你建立目录。
EXPOSE: 是声明运行时容器提供服务端口,这只是一个声明,在运行时并不会因为这个声明就会开启这个端口。
CMD: 用于指定默认容器主进程的启动命令(容器就是进程,在启动容器的时候需要指定所运行的程序及参数)。

Dockerfile 最佳实践

部分摘选

1. 在 Docker 官方的 Dockerfile 最佳实践文档中要求尽可能的使用 COPY,因为COPY 的语义很明确,就是复制文件而已,而 ADD 最适合使用的场景就是需要自动解压缩的场景。

2. 另外需要注意的是ADD 指令会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。

3. CMD 指令用于执行目标镜像中包含的软件可以包含参数,CMD 大多数情况下都应该以 CMD ["executable", "param1", "param2"...] 的形式使用,例如 CMD ["nginx", "-g", "daemon off;"]

4. RUN 与 CMD 的区别,RUN 在构建镜像时执行,CMD则是在镜像构建成功后在容器中执行。

本文分享自微信公众号 - 运维录(gh_70d95b8f5f7c),作者:东南

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-11-21

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Django容器(上): 自定义基础镜像

    某个 Python 项目,基于 Python:3.6 与 Django:1.11 框架开发,希望项目能够容器化,然后可以通过 docker-compose 等工...

    用户1560186
  • 如何删除无效的<none>Docker镜像?

    为什么会有 <none> 这样命名的镜像?这些镜像 docker 称为 虚悬镜像,当镜像被新的镜像覆盖时候,老版本镜像名称会变成 <none> 。

    用户1560186
  • 如何查找Docker中使用磁盘空间最多的容器?

    测试环境某台Docker主机触发磁盘空间报警,经过排查与分析发现是某个docker容器内的应用日志过大导致的,下面是具体的排查步骤。

    用户1560186
  • Dockerfile,你给我站住!

    Rainbond开源
  • Docker & ASP.NET Core (1):把代码连接到容器

    这样做的好处就是可以节省硬盘空间,也利于复用等等。因为Docker基于镜像创建容器的时候,其镜像是共享的;而且镜像里面的层如果已存在,也无需再下载。

    solenovex
  • Docker学习笔记之使用 Docker Hub 中的镜像

    自己编写 Dockerfile 能够很好的实现我们想要的程序运行环境,不过如果装有我们想要环境的镜像已经由热心的开发者构建好并共享在 Docker Hub 上,...

    Jetpropelledsnake21
  • 062. Dockerfile 构建私有镜像

    山海散人
  • 普元容器云关键设计和实践之路

    目前,DevOps,微服务与容器云,可以说是炙手可热的三大话题,甚至可以说它们是云时代企业新一代IT架构的三大基石也不为过。微服务主要解决的是开发期的设计问题,...

    yuanyi928
  • Docker 镜像构建:Python & Node

    在进行 Python 开发时,建议使用 pipenv 进行包管理,使用 node 中的 pm2 进行应用监控。本文将会简述如何构建一个 Python + Nod...

    凌虚
  • Docker 最佳实践

    1、每个容器只运行一个进程 2、配置和数据文件应该单独存储与备份。 3、使用.dockerignore 文件。在镜像构建过程中,Docker 会将Docke...

    用户5760343

扫码关注云+社区

领取腾讯云代金券

,,