本文转自 https://segmentfault.com/a/1190000016449865  , 感谢作者!

本文的源代码在:https://github.com/chanjarste...

这里先给出一些Docker Image制作的要求,之后我们再看怎么做。

  1. 制作过程要融合在项目构建过程中
  2. 使用官方Image作为基础Image
  3. 设定正确的时区
  4. Container内的程序以非root用户启动
  5. 指定Web程序的接口
  6. 能够传递JVM参数、Java System Properties、程序自定义的参数

下面具体讲一下具体怎么做到以上几点:

制作过程要融合在项目构建过程中

这里推荐使用Spotify的dockerfile-maven-plugin,理由是这个plugin用起来最简单且容易掌握。

该plugin的本质上是你写一个Dockerfile(关于Dockerfile的具体写法请参照官方文档),这个plugin把一些参数传递进去来帮助你构建Docker Image。

因此只要你会写Dockerfile,就会使用这个plugin,它没有加入任何额外的概念。

使用官方Image作为基础Image

Java的基础镜像应该在openjdk repository里寻找,而不是在已经过时的java repository里找。

openjdk repository提供了各种各样的image tags看起来眼花缭乱,但是本质上来说就这么几个:

  • openjdk:<version>
  • openjdk:<version>-slim
  • openjdk:<version>-alpine

关于<version>一般来说指定大版本号就行了,比如你可以在Dockerfile这样写:

FROM openjdk:8-alpine

从尺寸上来讲,alpine最小、slim稍大、默认的最大。所以应该尽可能的使用alpine版本的,如果发现程序的运行环境缺少某些东西,那么尝试用slim版本或者默认版本。就目前的经验来讲:

  • 如果需要操作系统字体库,那么就得使用slim版本或者默认版本。需要操作系统字体库的程序例如:图片验证码、PDF导出。
  • 如果需要某些Linux标准的动态/静态连接库,那么在alpine版本不行的情况下,尝试slim版本或默认版本。因为alpine版本是一个及其精简的Linux,它删除了很多东西。

设定正确的时区

几乎所有的Docker Image的时区都是UTC,我们需要给我们自己制作的Docker Image设定时区(参考的是SO的这个回答):

ENV TZ=Asia/Shanghai
RUN set -eux; \
ln -snf /usr/share/zoneinfo/$TZ /etc/localtime; \
echo $TZ > /etc/timezone

关于数据库时区的相关内容可以见:

Container内的程序以非root用户启动

在Docker Image内部,我们应该使用非root用户启动程序,这需要使用到gosu

gosu的Dockerfile指南在这里

记得要根据不同的基础Image选择适合的安装方式。

如果你用的是openjdk:<version>-alpine,那么直接用本项目提供的Dockerfile就行了。

如果你用的是openjdk:<version>-slim或者openjdk:<version>,那么在Image里安装gosu的方式是这样:

RUN set -ex; \
apt update; \
apt install -y gosu; \
rm -rf /var/lib/apt/lists/*; \
# verify that the binary works
gosu nobody true;

指定Web程序的接口

对于联网应用而言,必须在Dockerfile中指定暴露的端口,否则该端口无法映射。

EXPOSE 8080

能够传递JVM参数、Java System Properties、程序自定义的参数

我们需要能够在启动Docker Image的时候将一些参数传递进去:

  • JVM参数
  • Java System Properties
  • 程序启动参数

这里就需要参考Dockerfile best practiceDocker ENTRYPOINT了。

样例项目

样例项目源代码在这里:https://github.com/chanjarster/dockerfile-examples/

目录结构

所有与程序相关的东西都存放在/home/java-app/下:

/home/java-app
├── docker-entrypoint.sh
├── lib
│ └── java-app.jar
├── etc
├── logs
└── tmp
  • docker-entrypoint.sh,启动脚本
  • lib,存放JAR包
  • lib/java-app.jar,程序JAR包
  • etc,存放配置文件
  • logs,存放日志文件
  • tmp,存放临时文件

构建Image的方法

mvn clean package dockerfile:build

运行

普通启动,然后访问http://localhost:8080

docker run -p 8080:8080 chanjarster/dockerfile-java-examples-1:1.0-SNAPSHOT

设定JVM参数,使用JVM_OPTS环境变量:

docker run -p 8080:8080 -e JVM_OPTS='-Xmx128M -Xms128M' chanjarster/dockerfile-java-examples-1:1.0-SNAPSHOT

设定System Properties,使用JAVA_ARGS环境变量:

docker run -p 8080:8080 -e JAVA_ARGS='-Dabc=xyz -Ddef=uvw' chanjarster/dockerfile-java-examples-1:1.0-SNAPSHOT

提供程序运行参数,在后面直接添加即可:

docker run -p 8080:8080 chanjarster/dockerfile-java-examples-1:1.0-SNAPSHOT --debug

参考文档

docker 系列 - Java程序制作Docker Image推荐方案(转载)的更多相关文章

  1. Docker系列-(2) 镜像制作与发布

    上篇文章引入了Docker的基本原理和操作,本节文章主要介绍如何制作Docker镜像和发布. 镜像文件结构 Docker镜像的本质是一系列文件的集合,这些文件依次叠加,形成了最后的镜像文件,类似于下图 ...

  2. Docker极简入门:使用Docker运行Java程序

    运行简单的Java程序 先在当前目录创建App.java文件 public class App{ public static void main(String[] args){ String os = ...

  3. docker 运行java程序时区问题

    如果 docker  上面 java  的当前时间比,真实时间慢了8 小时,那估计就是时区问题了, 需要在 打包docker镜像的时候 带上 localtime 和  timezone.(这2 个文件 ...

  4. Docker系列-第七篇Docker构建SpringBoot应用

    1.基于Dockerfile构建SpringBoot镜像 1.1准备工作 将SpringBoot项目通过maven打成jar包 mvn clean package #使用maven打包项目 1.2使用 ...

  5. Docker系列(一)Docker概述,核心概念讲解,安装部署

    部分内容参考链接: Docker实战总结(非常全面,建议收藏) 一. Docker概述 Docker是一个开源的应用容器引擎(基于Go语言开发),让开发者可以打包他们的应用以及依赖包到一个可移植的容器 ...

  6. Docker系列教程01-使用Docker镜像

    docker系列导读 一文带你读懂什么是docker Docker安装部署 10张图带你深入理解Docker容器和镜像 前言 学习Docker,我们需要掌握它的三大核心概念:镜像.容器和仓库. 今天先 ...

  7. docker系列之一:初见docker

    什么是docker? docker是目前linux最流行的容器技术,Docker 将应用程序与该程序的依赖,打包在一个文件里面.运行这个文件,就会生成一个虚拟容器.程序在这个虚拟容器里运行,就好像在真 ...

  8. Docker系列06:Linux修改docker镜像和容器数据存储位置

    指定镜像和容器存放路径的参数是--graph=/var/lib/docker,其默认存储位置为/var/lib/docker, Docker 的配置文件可以设置大部分的后台进程参数,在各个操作系统中的 ...

  9. Java程序员进击书籍推荐

    计算机基础 计算机科学导论 计算机操作系统 操作系统原理及应用(Linux) Java 基础和进阶 疯狂Java讲义 Java 核心基础卷1/2 Java编程思想 Java 8实战 jls11 Eff ...

随机推荐

  1. 自学华为IoT物联网_06 智慧家庭物联网常见问题及解决方案

    点击返回自学华为IoT物流网 自学华为IoT物联网_06 智慧家庭物联网常见问题及解决方案 1. 家庭中遇到的问题 2.1 华为智慧家庭概念的发展历程 2.2 华为智慧家庭的解决方案架构 智慧家庭主要 ...

  2. 【BZOJ5292】[BJOI2018]治疗之雨(高斯消元)

    [BZOJ5292][BJOI2018]治疗之雨(高斯消元) 题面 BZOJ 洛谷 题解 设\(f[i]\)表示剩余\(i\)点生命时的期望死亡的次数. 考虑打\(k\)次下来脸上被打了\(i\)下的 ...

  3. 【转】gcc 编译使用动态链接库和静态链接库

    1 库的分类 根据链接时期的不同,库又有静态库和动态库之分. 静态库是在链接阶段被链接的(好像是废话,但事实就是这样),所以生成的可执行文件就不受库的影响了,即使库被删除了,程序依然可以成功运行. 有 ...

  4. 编写高质量代码:改善Java程序的151个建议 --[65~78]

    编写高质量代码:改善Java程序的151个建议 --[65~78] 原始类型数组不能作为asList的输入参数,否则会引起程序逻辑混乱. public class Client65 { public ...

  5. [USACO18JAN]Sprinklers

    [USACO18JAN]Sprinklers 一个矩形要符合什么条件 右上角的右上有点,左下角的左下有点 所以每列的选择高度为一个区间,小于后缀最大值大于前缀最小值(不管是作为右上角还是左下角) 然后 ...

  6. 洛谷P1117 优秀的拆分

    题意:求一个字符串中有多少形如AABB的子串. 解:嗯...我首先极度SB的想了一个后缀自动机套线段树启发式合并的做法,想必会TLE. 然后跑去看题解,发现实在是妙不可言... 显然要对每个位置求出向 ...

  7. wave

    题意:求有多少个1~n的排列满足: 其中n<=50 解: 贼神的一道题. 如何处理绝对值? 从小到大按顺序放数,可以拆掉绝对值. 如果你放的旁边有个空隙,那么贡献-i,如果旁边有个数,贡献+i ...

  8. react-native中的请求数据

    很多移动应用都需要从远程地址中获取数据或资源.你可能需要给某个 REST API 发起 POST 请求以提交用户数据,又或者可能仅仅需要从某个服务器上获取一些静态内容. 使用 Fetch React ...

  9. 有趣的js获取input标签中光标的索引

    先看动图如下,我们就可以很清楚的知道获取input标签中光标的索引的意思了. 由于IE支持document.selection,Firefox,Chrome,Safari以及Opera都有select ...

  10. django基于中间件的IP访问频率控制

    一.中间件的代码 注意:成功时返回的是None,那样才会走视图层,返回httpresponse就直接出去了 import time from django.utils.deprecation impo ...