本文已迁移到我的新博客地址,欢迎访问:
许多Docker镜像都是开箱即用的,但有时候却并不一定满足我们的需求,比如,你直接从Docker Hub拉取的tomcat 使用的Java VM是Open JDK,但通常我们需要使用Oracle JDK。由于版权问题,Docker Hub无法提供基于Oracle的JDK,这时我们就需要深度定制符合我们需求的镜像了。
镜像属于 docker build的组件,主要使用Dockerfile来完成镜像的上下文定义。
目标:制作基于Oracle JDK 的Java 应用运行环境.
提示:在制作镜像时,应该遵守复用原则,不要将所有东西都一次性打包到一个镜像,应该根据需要,将不同功能模块制作成单独的镜像,本文将环境分为三层:base os层,jre层,tomcat层。其中每一层都可继续用于其他镜像的制作。
每个镜像都有一个基础镜像,做为基础,类似于继承,大多数镜像最终都来源于scratch
镜像,该镜像是一个空的镜像,主要用于制作其他镜像,大多数时候你并不需要从该镜像开始,除非你要制作一个系统镜像。我们这里并不使用该镜像,因为我们关注的是应用层,所以起点选择在操作系统之上,这里我选择的是Ubuntu发行版最新稳定版16.04:
$ docker pull ubuntu:16.04
等待拉取完毕,大小约130M。
$ mkdir baseos
该目录作为我们构建镜像的上下文,构建该镜像的所有内容都会放到该目录下。
$ cd baseos
$ touch Dockerfile
该命令会创建一个空白文本文档。
$ vi Dockerfile
# Base os image
FROM ubuntu:16.04
MAINTAINER your_name
LABEL Description="This image is the base os images." Version="1.0"
# reconfig timezone
RUN echo "Asia/Shanghai" > /etc/timezone \
&& dpkg-reconfigure -f noninteractive tzdata
说明:
#
开头的行为注释;FROM
关键字告诉docker我们的新镜像基于哪个基础镜像;MAINTAINER
关键字是维护者信息,可以修改为你的名字和邮箱地址;LABEL Description
是对镜像的一个简单说明,Version
指明该镜像的版本号,方便维护;RUN
关键字用于执行一条命令。这里主要是修改系统的时区从标准UTC改为亚洲/上海。现在,我们已经准备好构建镜像了,执行docker build -t example.com/baseos:1.0 .
命令构建,注意不要忘了最后的那个点.
:
$ docker build -t example.com/baseos:1.0 .
Sending build context to Docker daemon 2.048 kB
Step 1 : FROM ubuntu:16.04
---> f8d79ba03c00
Step 2 : MAINTAINER your_name <your_email_address>
---> Using cache
---> fd4f32d5433d
Step 3 : LABEL Description "This image is the base os images." Version "1.0"
---> Using cache
---> 71b121420b3b
Step 4 : RUN echo "Asia/Shanghai" > /etc/timezone && dpkg-reconfigure -f noninteractive tzdata
---> Using cache
---> eca2b07b46e8
Successfully built eca2b07b46e8
查看我们的新镜像:
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
example.com/baseos 1.0 eca2b07b46e8 2 weeks ago 127.6 MB
根据你的环境需要,下载不同版本的JRE,注意一定是Linux x64版本。本文选择JRE 7u80
注:Oracle Java 目前的版本为 Java 8,可直接下载。要下载以前的版本需注册Oracle帐户登录方可下载。另外,如果你已有安装过的JDK(Linux),也可直接将$JAVA_HOME/jre目录打包待用。
下载好后,解压到一个目录,将目录中的jre子目录打包:
# 重命名文件夹
$ mv jre jre1.7.0_80
# 打包
$ tar -zcvf jre-7u80-linux-x64.tar.gz jre1.7.0_80
生成:
jre-7u80-linux-x64.tar.gz
$ mkdir jre-7u80
$ cp jre-7u80-linux-x64.tar.gz jre-7u80
$ cd jre-7u80
$ touch Dockerfile
该命令会创建一个空白文本文档。
$ vi Dockerfile
# Base jre image
FROM example.com/baseos:1.0
MAINTAINER your_name <your_email_address>
LABEL Description="This image is used to serve Oracle jre 7u80" Version="1.0"
# Install and config Oracle jre
ADD jre-7u80-linux-x64.tar.gz /usr/lib/jvm/
RUN update-alternatives --install "/usr/bin/java" "java" "/usr/lib/jvm/jre1.7.0_80/bin/java" 1 \
&& update-alternatives --set java /usr/lib/jvm/jre1.7.0_80/bin/java
ENV JAVA_HOME /usr/lib/jvm/jre1.7.0_80
说明:
ADD
关键字会复制新的文件目录或远程文件链接到docker的文件系统。注意:有复制功能的还有另一个关键字COPY
,简单来说,ADD
除了普通的复制功能外,还具有一些微妙的特殊功能,比如,在复制一个tar.gz包时,它会默认解压到目标文件系统。ENV
关键字用于设置环境变量,以
的形式,该环境变量会作用于所有后续Dockerfile命令。$ docker build -t example.com/jre:7u80 .
$ docker run --rm example.com/jre:7u80 java -version
java version "1.7.0_80"
Java(TM) SE Runtime Environment (build 1.7.0_80-b15)
Java HotSpot(TM) 64-Bit Server VM (build 24.80-b11, mixed mode)
--rm
选项可以在容器运行完毕立即删除容器。
根据需要下载相应版本的tar.gz包,这里下载的是Tomcat7。
$ mkdir tomcat7-jre7
$ cp apache-tomcat-7.0.70.tar.gz tomcat7-jre7
$ cd tomcat7-jre7
$ touch Dockerfile
$ vi Dockerfile
# Base image
FROM example.com/jre:7u80
MAINTAINER your_name <your_email_address>
LABEL Description="This image is used to run tomcat7 with jre7." Version="1.0"
ENV CATALINA_HOME /var/lib/tomcat7
ENV PATH $CATALINA_HOME/bin:$PATH
WORKDIR $CATALINA_HOME
ADD apache-tomcat-7.0.70.tar.gz /var/lib/
RUN mv /var/lib/apache-tomcat-7.0.70 $CATALINA_HOME \
&& rm -rf /var/lib/tomcat7/bin/*.bat
EXPOSE 8080
CMD ["catalina.sh", "run"]
说明:
WORKDIR
关键字定义了环境的工作目录,类似于Linux下的chroot。EXPOSE
关键字用于暴露容器中可用的端口,注意它并不能直接将端口映射到主机,你需要使用-p
选项来指定。CMD
关键字用来提供容器运行时默认执行的命令。一个Dockerfile
中只能有一个CMD
,如果存在多个,则只有最后一个会生效。注意: 要让一个容器保持运行状态而不退出,容器默认执行的命令需要在前台运行,而不是在后台,这与我们通常在Linux环境下设置应用在后台运行有所不同,如果你将容器中的应用设置为后台运行的话,容器启动完会立马退出。
$ docker build -t example.com/tomcat:7-jre7 .
$ docker run -d --name mytomcat1 -p 8088:880 example.com/tomcat:7-jre7
c079ebcb690e60177b246879d28f483074e6e2454b812673f6336d17bdafb301
访问192.168.1.132:8088,查看结果:
到此,我们的环境就全部构建完毕,你可以将这几个镜像用于你的日常开发了。欢迎讨论交流更多Docker的用法。
关于如何书写更好的Dockerfile
文件,推荐去阅读一下官方的最佳实践,和完整的Dockerfile参考,并在你的应用中谨遵这些最佳实践。
(完)
本文已迁移到我的新博客地址,欢迎访问: