本文转自 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. flowable6.4.1+springboot使用dmn

    resources/dmn/strings_1.dmn <?xml version="1.0" encoding="UTF-8"?> <def ...

  2. ALLOT流控设备操作手册指引

    ALLOT流控设备操作手册指引 1  简介 1.1 设备介绍 1.1.1 NetXploeer三层结构 Allot设备的管理如上图所示,采用三层结构. 1)NetEnforcer层,包括所有型号的Ne ...

  3. PyCharmMarkdown插件的方法

    arkdown是一种可以使用普通文本编辑器编写的标记语言,通过简单的标记语法,它可以使普通文本内容具有一定的格式. 从github下载的代码一般都会带有README.md文件,该文件是一个Markdo ...

  4. [POI2007]ODW-Weights(贪心)

    在byteotian公司搬家的时候,他们发现他们的大量的精密砝码的搬运是一件恼人的工作.公司有一些固定容量的容器可以装这些砝码.他们想装尽量多的砝码以便搬运,并且丢弃剩下的砝码.每个容器可以装的砝码数 ...

  5. centos7 下解决mysql-server找不到安装包问题

    第一步:安装从网上下载文件的wget命令 [root@master ~]# yum -y install wget 第二步:下载mysql的repo源 [root@master ~]# wget ht ...

  6. Jupyter-Notebook服务器自定义密码

    往期回顾 Anaconda安装:https://www.cnblogs.com/dotnetcrazy/p/9158715.html 基本知识导航篇:https://www.cnblogs.com/d ...

  7. Python数据结构之栈的实现

    一图胜千言,看图! 代码code: #coding:utf-8 #常见数据结构之栈的实现 class Stack(): #创建Stack类 def __init__(st,size): st.stac ...

  8. 用宏定义代替printf函数

    来自:http://blog.csdn.net/yannanxiu/article/details/52506451 #define _DEBUG_ 1 #if _DEBUG_ #define PR( ...

  9. Django(十三)ajax 与 Bootstrap,font-awesome

    prop,attr,val font-awesome:字体,图标库 对话框添加,删除,修改: 添加: Ajax偷偷向后台发请求: 1. 下载引入jQuery 2. $.ajax({ url: '/ad ...

  10. 回流(reflow)与重绘(repaint)

    回流(reflow)与重绘(repaint) 很早之前就听说过回流与重绘这两个名词,但是并不理解它们的含义,也没有深究过,今天看了一套网易的题目,涉及到了这两个概念,于是想要把它们俩弄清楚... 一. ...