构建Tomcat镜像
FROM centos:7
MAINTAINER zhangyingguang
# 将宿主机的jdk文件拷至镜像的/usr/local目录下,会自动解压
ADD jdk-8u45-linux-x64.tar.gz /usr/local
# 设置环境变量
ENV JAVA_HOME /usr/local/jdk1.8.0_45
ADD apache-tomcat-8.0.46.tar.gz /usr/local
# 拷贝文件或目录到镜像中,用法同ADD,只是不支持自动下载和解压
COPY server.xml /usr/local/apache-tomcat-8.0.46/conf
# 删除tar包
RUN rm -rf /usr/local/*.tar.gz
WORKDIR /usr/local/apache-tomcat-8.0.46
# 暴露端口
EXPOSE 8080
# 设置启动命令
ENTRYPOINT ["./bin/catalina.sh","run"]
创建镜像、创建容器
docker build -t tomcat:v1 .
docker run -itd --name=tomcate -p 8080:8080 \
-v /app/webapps/:/usr/local/apache-tomcat-8.0.46/webapps/ \
tomcat:v1
镜像优化
- 一次RUN指令形成新的一层,尽量Shell命令都写在一行,减少镜像层。
- 一次RUN形成新的一层,如果没有在同一层删除,无论文件是否最后删除,都会带到下一层,所以要在每一层清理对应的残留数据,减小镜像大小。
- 精简镜像 https://blog.csdn.net/M2l0ZgSsVc7r69eFdTj/article/details/81977225
Dockerfile关键字解释
FROM(指明构建的新镜像是来自于哪个基础镜像)
FROM centos:7
MAINTAINER(用来指定镜像创建者信息)
MAINTAINER zhangyingguang@situdata.com
RUN(安装软件用)
该指令有两种格式:
RUN [“yum”, “install”, “httpd”]
RUN yum install httpd
CMD(启动容器时执行的Shell命令)
该指令有三种格式:
CMD [“-C”, “/start.sh”]
CMD [“/usr/sbin/sshd”, “-D”]
CMD /usr/sbin/sshd -D
当Dockerfile指定了ENTRYPOINT,那么使用下面的格式:
CMD [“param1”,”param2”] (as default parameters to ENTRYPOINT)
ENTRYPOINT(启动容器时执行的Shell命令,同CMD类似,只是由ENTRYPOINT启动的程序不会被docker run命令行指定的参数所覆盖,而且,这些命令行参数会被当作参数传递给ENTRYPOINT指定指定的程序)
两种格式:
ENTRYPOINT [“/bin/bash”, “-C”, “/start.sh”]
ENTRYPOINT /bin/bash -C ‘/start.sh’
注意:Dockerfile文件中也可以存在多个ENTRYPOINT指令,但仅有最后一个会生效。
USER(设置container容器的用户)
USER root
EXPOSE(指定容器需要映射到宿主机器的端口)
EXPOSE 80 443
ENV(用于设置环境变量)
ENV MYSQL_ROOT_PASSWORD 123456
ENV JAVA_HOME /usr/local/jdk1.8.0_45
ADD(拷贝文件或目录到镜像中)
ADD html.tar.gz /var/www/html
ADD https://xxx.com/html.tar.gz /var/www/html
注意:如果是URL或压缩包,会自动下载或自动解压。
COPY(拷贝文件或目录到镜像中,用法同ADD,只是不支持自动下载和解压)
COPY ./start.sh /start.sh
VOLUME(指定容器挂载点到宿主机自动生成的目录或其他容器))
VOLUME [“/var/lib/mysql”]
注意:一般不会在Dockerfile中用到,更常见的还是在docker run的时候指定-v数据卷。
WORKDIR(登陆容器默认目录)
WORKDIR /data
ONBUILD(在子镜像中执行)
格式: ONBUILD
补充(CMD和ENTRYPOINT的区别)
CMD(启动容器时执行的Shell命令,CMD启动的程序会被docker run命令行指定的参数所覆盖,)因为CMD命令很容易被docker run命令的方式覆盖, 所以, 如果你希望你的docker镜像的功能足够灵活, 建议在Dockerfile里调用CMD命令。
ENTRYPOINT(启动容器时执行的Shell命令,同CMD类似,只是由ENTRYPOINT启动的程序不会被docker run命令行指定的参数所覆盖,而且,这些命令行参数会被当作参数传递给ENTRYPOINT,entrypoint会把/bin/bash当成一个echo的字符串参数,不会进入到容器中。)
ENTRYPOINT的作用不同, 如果你希望你的docker镜像只执行一个具体程序, 不希望用户在执行docker run的时候随意覆盖默认程序. 建议用ENTRYPOINT.
Docker在很多情况下被用来打包一个程序. 想象你有一个用python脚本实现的程序, 你需要发布这个python程序. 如果用docker打包了这个python程序, 你的最终使用用户就不需要安装python解释器和python的库依赖,你可以把所有依赖工具打包进docker镜像里,然后用ENTRYPOINT指向你的Python脚本本身,当然你也可以用CMD命令指向Python脚本,但是通常用ENTRYPOINT可以表明你的docker镜像只是用来执行这个python脚本,也不希望最终用户用这个docker镜像做其他操作.
[root@Optimus docker-training]# vim Dockerfile
FROM centos:centos7.1.1503
ENTRYPOINT ["/bin/echo", "This is test entrypoint"]
[root@Optimus docker-training]# docker run -it csphere/ent:0.1 /bin/bash
This is test entrypoint /bin/bash
注意:Dockerfile文件中也可以存在多个ENTRYPOINT指令,但仅有最后一个会生效。
组合使用
定义了 ENTRYPOINT 的话,CMD 只为 ENTRYPOINT 提供参数
FROM ubuntu:trusty
ENTRYPOINT ["/bin/ping","-c","3"]
CMD ["localhost"]
[root@Optimus docker-training]# docker run demo
PING localhost (127.0.0.1) 56(84) bytes of data.
64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.025 ms
64 bytes from localhost (127.0.0.1): icmp_seq=2 ttl=64 time=0.038 ms
64 bytes from localhost (127.0.0.1): icmp_seq=3 ttl=64 time=0.051 ms
--- localhost ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1999ms
rtt min/avg/max/mdev = 0.025/0.038/0.051/0.010 ms
上面执行的命令是ENTRYPOINT和CMD指令拼接而成.,ENTRYPOINT和CMD同时存在时, docker把CMD的命令拼接到ENTRYPOINT命令之后, 拼接后的命令才是最终执行的命令. 但是由于上文说docker run命令行执行时, 可以覆盖CMD指令的值. 如果你希望这个docker镜像启动后不是ping localhost, 而是ping其他服务器,可以这样执行docker run