如何通过Dockerfile快速构建镜像
Docker:最早是dotCloud公司出品的一套容器管理工具,但后来Docker慢慢火起来了,连公司名字都从dotCloud改成Docker。
Dockerfile: 它是Docker镜像的描述文件,可以理解成火箭发射的A、B、C、D……的步骤。
Docker镜像: 通过Dockerfile做出来的,包含操作系统基础文件和软件运行环境,它使用分层的存储方式。
容器: 是运行起来的镜像,简单理解,Docker镜像相当于程序,容器相当于进程。
接下来,我们通过构建一个Tomcat镜像,来演示Dockerfile的使用方法,当然前提是你的电脑安装了Docker环境,如何安装Docker环境就不在此赘述了。
1、创建一个Dockerfile
Dockerfile命名必须为“Dockerfile”,Docker镜像构建时,会查找指定目录中的Dockerfile。
2、编写Dockerfile
(1)环境配置
FROM centos:7.6.1810
- Dockerfile文件是以FROM指令开始的,通过该指令从docker hub上或者本地存储库中拉取镜像作为基本镜像。
- 通过FROM指令,Docker编译程序能够知道通过哪个基础镜像执行来进行编译。
- 所有的Dockerfile都必须以FROM指令开始。通过该指令,我们相当于有了一个最基本的Ubuntu系统。
- 镜像的名称和标签可以去Docker Hub或者使用命令docker search keyword 进行搜索
(2)其他环境配置
MAINTAINER jinyue.li <40021310@qq.com>
另外我们需要指定时区,否则我们做出的镜像可能会跟当前时间不符。
RUN echo "Asia/Shanghai" > /etc/timezone;
我们可以像在电脑上安装Tomcat一样,把Tomcat安装在Docker容器中。
(3)Tomcat必要软件安装。
我们此时使用的系统其实是很简陋的系统,上面很多系统都没有。所以我先安装一些必要的软件。
RUN yum update && yum install -y curl vim net-tools && \
rm -rf /var/lib/apt/lists/* && mkdir -p /app
RUN 指令用来在Docker的编译环境中运行指定命令。这里我安装了curl、vim、net-tools,其中curl用来获取java和tomcat的安装包,vim和net-tools用来调试,并创建了/app目录。
RUN有两种形式:
- RUN (shell形式)
- RUN [“executable”, “param1”, “param2”](exec形式)
exec形式被解析为JSON数组,这意味着必须使用双引号(“),而不是单引号(‘)
该RUN指令将在当前镜像之上的新层中执行任何命令并提交结果。生成的提交镜像将用于下一步Dockerfile。
RUN在下一次构建期间,指令的缓存不会自动失效。类似指令的缓存
RUN yum dist-upgrade -y
将在下一次构建期间重用。例如,RUN可以通过使用–no-cache标志使指令的高速缓存无效
docker build --no-cache .
注意:
- 将多个RUN指令合并为一个
- 基础镜像的标签不要用latest
- 每个RUN指令后删除多余文件
使用\将多个RUN指令合成一个,可以有效减少容器层数以及镜像大小,当我们更新了apt-get源,下载安装了一些软件包,它们都保存在/var/lib/apt/lists/目录中。但是,运行应用时Docker镜像中并不需要这些文件。最好将它们删除,因为这会使Docker镜像变大。
FROM ubuntu:18.04
RUN apt-get update && \
apt-get install -y nginx && \
apt-get install -y nodejs && \
&& rm -rf /var/lib/apt/lists/*
(4)指定工作目录
使用 WORKDIR /app 可以将工作目录定位到/app 目录下
(5)获取安装软件
我们使用 第 (3)步 安装的 curl 工具来获取安装包。
RUN curl -L 'http://download.oracle.com/otn-pub/java/jdk/7u65-b17/jdk-7u65-linux-x64.tar.gz' -H 'Cookie: oraclelicense=accept-securebackup-cookie; gpw_e24=Dockerfile' | tar -xz \
&& curl -L 'http://archive.apache.org/dist/tomcat/tomcat-7/v7.0.8/bin/apache-tomcat-7.0.8.tar.gz' | tar -xz
以上命令将会从指定地址下载安装包,并解压到当前目录(上一步我们指定了工作空间为/app,所以会解压到此目录下)
(6)指定运行脚本
截止到上一步,我们已经将需要的准备工作都做好了,剩下的还有Java环境变量的设置,Tomcat环境变量设置(非必须)和Tomcat的启动。
COPY tomcat7.sh /app/tomcat7.sh
RUN chmod +x /app/tomcat7.sh
上面的两行命令会将与Dockerfile同级目录的tomcat7.sh文件上传到docker容器中的/app目录下,并且给该文件赋予可执行的权限。
看一眼tomcat7.sh脚本的内容便一目了然了。
# Java环境变量配置
export JAVA_HOME=/app/jdk1.7.0_65
export PATH=$JAVA_HOME/bin:$PATH
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
# Tomcat环境变量配置
export TOMCAT_HOME=/app/apache-tomcat-7.0.8
export PATH=$TOMCAT_HOME/bin:$PATH
# 启动 Tomcat
exec $TOMCAT_HOME/bin/catalina.sh run
(7)指定端口
EXPOSE 8080
通常情况下,Tomcat启动后会监听8080端口,在容器中也一样。
EXPOSE指令用于标明,这个镜像中的应用将会侦听某个端口,并且希望能将这个端口映射到主机的网络界面上
(8)指定脚本的运行
至此,我们要做的准备工作就做完了。使用下面这条命令,运行我们在第6步创建的脚本,一个简单的Tomcat的Dockerfile就编写完成了。
ENTRYPOINT [“/app/tomcat7.sh"]
ENTRYPOINT 用于标明一个镜像作为容器运行时,最后要执行的程序或命令。
(9)Dockerfile完整内容
FROM centos:7.6.1810
MAINTAINER example <example@goodrain.com>
RUN echo "Asia/Shanghai" > /etc/timezone;
RUN yum update && yum install -y curl vim net-tools && rm -rf /var/lib/apt/lists/* \
&& mkdir -p /app
## Install JDK 7
WORKDIR /app
RUN curl -L 'http://download.oracle.com/otn-pub/java/java_ee_sdk/8/java_ee_sdk-8u1.zip' -H 'Cookie: oraclelicense=accept-securebackup-cookie; gpw_e24=Dockerfile' | unzip \
&& curl -L 'http://archive.apache.org/dist/tomcat/tomcat-7/v7.0.8/bin/apache-tomcat-7.0.8.tar.gz' | tar -xz
# copy scripts to docker container
COPY run.sh /app/run.sh
COPY tomcat7.sh /app/tomcat7.sh
RUN chmod +x /app/run.sh
RUN chmod +x /app/tomcat7.sh
COPY java-war.war /app/java-war.war
# Expose ports.
EXPOSE 8080
# Define default command.
ENTRYPOINT ["/app/tomcat7.sh"]
#ENTRYPOINT ["/app/run.sh"]
3.构建镜像
进入Dockerfile所在目录,运行命令
docker build -t mytomcat .
- 注意最后有个点用来表示当前目录,初次构建速度会比较慢,需要多等一会。
使用当前目录下的Dockerfile文件创立新的镜像,但是REPOSITORY和TAG都是默认的None
docker build .
可以使用-f标志docker build指向文件系统中任何位置的Dockerfile。
docker build -f /path/Dockerfile .
如果构建成功,该命令可以指定存储库和标记以保存新镜像。
docker build -t REPOSITORY:TAG .
要在构建后将映像标记为多个存储库,请在-t运行build命令时添加多个参数:
docker build -t REPOSITORY1:TAG1 -t REPOSITORY2:TAG2 .
4.运行Docker容器
docker run -i -t -p 5000:8080 mytom
其中,docker run 用于运行一个容器
- t 在容器指定一个伪终端或者终端;
- i 进行命令交互;
- p 匹配镜像内的网络端口号,即我们可以通过宿主机中访问5000端口来达到访问容器8080端口的目的。
5.查看构建好的镜像和运行的容器
docker images #查看镜像
docker ps -a #查看所有的容器
6.查看服务是否运行
在宿主机中我们输入localhost:5000访问,出现Tomcat欢迎界面,表示Tomcat成功运行。
至此,我们就成功的创建了一个Tomcat镜像了,当然这里只是为了简单演示,所以镜像做的比较简单,官方的Tomcat镜像比这复杂的多,在熟悉了Dockerfile后可以去看看官方的做法。
7.技巧
在做镜像的时候有那么多步骤,根本不可能一次将所有的步骤完成,所以,这里教给大家一个 小技巧。
在编写完Dockerfile到第二步的时候,其实可以先使用一个脚本先运行着,然后进入容器内部进行操作。笔者在编写Dockerfile时先使用如下命令
COPY run.sh /app/run.sh
RUN chmod +x /app/run.sh
ENTRYPOINT ["/app/run.sh"]
run.sh脚本的内容如下
#!/bin/bash
sleep 15
while true
do
echo "true"
sleep 180
done
其实就是一段死循环代码代替原有的tomcat7.sh,接着就可以build和run我们的容器了。容器运行起来后使用
docker exec -it container_id bash #进入docker容器
此时就和我们平时装软件的方式一样了,做完一个步骤,在Dockerfile中记录一条,这样Dockerfile也就做出来了。
exit #退出容器
特别注意的一点,如果做好镜像以后,在镜像中有需要保存的数据(持久化目录)需要我们在Dockerfile中指定持久化目录。为了能够保存(持久化)数据以及共享容器间的数据,Docker提出了Volume的概念。简单来说,Volume就是目录或者文件,它可以绕过默认的联合文件系统,而以正常的文件或者目录的形式存在于宿主机上。并且我们运行容器的时候需要使用使用 -v 来声明Volume,如:
docker run -it -v /home/dock/logs:/usr/logs tomcat /bin/bash
冒号前为宿主机目录,必须为绝对路径,冒号后为镜像内挂载的路径,这样容器内更改的数据就被写到宿主机上了。
拥有了Tomcat服务器后,就可以跑写好的java-web程序了,如何运行java-web程序就不在此详述了,跟普通运行java-web程序一样。
同样的,如果你有一个web应用,将其放入Docker容器中,写好Dockerfile,构建好应用运行需要的环境后,就可以很快的使用应用了。