Docker镜像制作方法及Dockerfile企业级简单解析

由于Docker官网公共仓库镜像大多不完整,无法真正满足企业的生产环境系统,此时需要我们自行定制镜像或者重新打包镜像。Docker镜像制作是管理员的必备工作之一,Docker镜像制作的方法主要有两种,制作方法如下:

  • Docker commit|export将新容器提交至Images列表;
  • 编写Dockerfile,bulid新的镜像至镜像列表;

一、commit方式

  • 从Docker仓库中下载基础镜像;
    docker pull docker.io/jdeathe/centos-ssh

  • Docker run基础镜像,生成容器;
    docker run -itd -p 6022:22 --privileged -name aliyun-server docker.io/jdeathe/centos-ssh

  • 进入容器-安装软件、添加功能、创建目录、文件;

#这里可以将你这个虚拟机需要的基础环境安装上,比如部署一个LNMP架构,或者我只想用一个web服务器,只用安装一个nginx即可!
yum install wget zlib-devel pcre-devel gcc-c++ -y
wget -O /usr/local/nginx-1.16.0.tar.gz http://nginx.org/download/nginx-1.16.0.tar.gz
tar xvf /usr/local/nginx-1.16.0.tar.gz
cd /usr/local/nginx-1.16.0
./configure --prefix=/usr/local
make -j4&make install
wget -O /usr/local/nginx/html/index.html http://www.baidu.com
echo "PATH=$PATH:/usr/local/nginx/sbin/" >>/etc/profile
source /etc/profile
  • Docker commit 容器ID,将容器提交为新的镜像;
    docker commit c432b9da999c
    在这里插入图片描述在这里插入图片描述
  • Docker save将镜像列表中的镜像导入为tar包;
    docker save centos-v2:latest -o /root/centos-v2.tar
  • Docker load镜像tar包,导入镜像列表。
    注:先scp到目标服务器,再执行下面操作
    docker load -i /root/centos-v2.tar

二、Export方式

  • 从Docker仓库中下载基础镜像;
  • Docker run基础镜像,生成容器;
  • 进入容器-安装软件、添加功能、创建目录、文件;
  • Docker export 容器ID,将容器导出为镜像tar包(丢失内存中的数据文件,企业中不推荐该方案);
docker ps
docker export c432b9da999c(容器ID) >/root/centos-v3.tar
  • Docker import将镜像tar包,导入镜像列表。
 cat /root/centos-v3.tar|docker import - centos-v3
 -:占位符
 centos-v3:指定REPOSITORY

在这里插入图片描述注:以上两种方式的区别是,commit方法多了一个将容器提交成为镜像的步骤,Export方式直接将容器变成镜像再导出,合成一步了。但是这样虽然方便,但是可能会有数据损失,所以一般不采用Export方法!

三、Dockerfile企业级制作方法(推荐)

1、Dockerfile制作原理
将基于一个基础镜像,通过编写Dockerfile方式,将各个功能进行叠加,最终形成新的Docker镜像,是目前互联网企业中打包镜像最为推荐的方式。

Dockerfile是一个镜像的表示,也是一个镜像的原材料,可以通过Dockerfile来描述构建镜像,并自动构建一个容器。

2、如下为DockerFile制作镜像,必备的指令和参数的详解:
FROM	 		指定所创建镜像的基础镜像;
MAINTAINER		指定维护者信息;
RUN				运行命令;
CMD				指定启动容器时默认执行的命令;
LABEL			指定生成镜像的元数据标签信息;
EXPOSE			声明镜像内服务所监听的端口;
ENV				指定环境变量;
ADD				赋值指定的<src>路径下的内容到容器中的<dest>路径下,<src>可以为URL;如果为tar文件,会自动解压到<dest>路径下
COPY			赋值本地主机的<scr>路径下的内容到容器中的<dest>路径下;一般情况下推荐使用COPY而不是ADD;
ENTRYPOINT		指定镜像的默认入口;
VOLUME			创建数据挂载点;
USER			指定运行容器时的用户名或UID;
WORKDIR			配置工作目录;
ARG				指定镜像内使用的参数(例如版本号信息等);
ONBUILD			配置当前所创建的镜像作为其他镜像的基础镜像时,所执行的创建操作的命令;
STOPSIGNAL		容器退出的信号;
HEALTHCHECK		如何进行健康检查;
SHELL			指定使用SHELL时的默认SHELL类型;
3、编写DockerFile最佳实践
(1)减少镜像层

一次RUN指令形成新的一层,尽量Shell命令都写在一行,减少镜像层。 例如:

FROM centos:7
MAINTAINER www.baidu.com
RUN yum install epel-release -y 
RUN yum install -y gcc gcc-c++ make -y
RUN wget http://docs.php.net/distributions/php-5.6.36.tar.gz
RUN tar zxf php-5.6.36.tar.gz
RUN cd php-5.6.36
RUN ./configure --prefix=/usr/local/php 
RUN make -j 4 
RUN make install
EXPOSE 9000
CMD ["php-fpm"]

应该写成:

FROM centos:7
MAINTAINER www.baidu.com
RUN yum install epel-release -y && \
    yum install -y gcc gcc-c++ make

RUN wget http://docs.php.net/distributions/php-5.6.36.tar.gz && \
    tar zxf php-5.6.36.tar.gz && \
    cd php-5.6.36 && \
    ./configure --prefix=/usr/local/php && \
    make -j 4 && make install
EXPOSE 9000
CMD ["php-fpm"]
(2)优化镜像大小:清理无用数据

一次RUN形成新的一层,如果没有在同一层删除,无论文件是否最后删除,都会带到下一层,所以要在每一层清理对应的残留数据,减小镜像大小。

FROM centos:7
MAINTAINER www.baidu.com
RUN yum install epel-release -y && \
    yum install -y gcc gcc-c++ make gd-devel libxml2-devel \
    libcurl-devel libjpeg-devel libpng-devel openssl-devel \
    libmcrypt-devel libxslt-devel libtidy-devel autoconf \
    iproute net-tools telnet wget curl && \
    yum clean all && \
    rm -rf /var/cache/yum/*

RUN wget http://docs.php.net/distributions/php-5.6.36.tar.gz && \
    tar zxf php-5.6.36.tar.gz && \
    cd php-5.6.36 && \
    ./configure --prefix=/usr/local/php \
    make -j 4 && make install && \
    cd / && rm -rf php*

至少能节省几十M,甚至几百M。

(3)减少网络传输时间

最好在内部有一个存放软件包的地方,类似于上述的PHP官方下载地址:http://docs.php.net/distributions/php-5.6.36.tar.gz ,如果用到maven构建这样的操作,同时也更改为私有maven仓库,减少网络传输时间,提高镜像构建速度。

(4)多阶段进行镜像构建

如果运行一个项目,根据咱们上面的做法,是直接把代码拷贝到基础镜像里,如果是一个需要预先代码编译的项目呢?例如JAVA语言,如何代码编译、部署在一起完成呢!

上面做法需要事先在一个Dockerfile构建一个基础镜像,包括项目运行时环境及依赖库,再写一个Dockerfile将项目拷贝到运行环境中,有点略显复杂了。

像JAVA这类语言如果代码编译是在Dockerfile里操作,还需要把源代码构建进去,但实际运行时只需要构建出的包,这种把源代码放进去有一定安全风险,并且也增加了镜像体积。 为了解决上述问题,Docker 17.05开始支持多阶段构建(multi-stage builds),可以简化Dockerfile,减少镜像大小。

例如,构建JAVA项目镜像:

$ git clone https://github.com/lizhenliang/tomcat-java-demo
$ cd tomcat-java-demo
$ vi Dockerfile
FROM maven AS build
ADD ./pom.xml pom.xml
ADD ./src src/
RUN mvn clean package

FROM lizhenliang/tomcat
RUN rm -rf /usr/local/tomcat/webapps/ROOT
COPY --from=build target/*.war /usr/local/tomcat/webapps/ROOT.war

$ docker build -t demo:v1 .
$ docker container run -d -v demo:v1

首先,第一个FROM 后边多了个 AS 关键字,可以给这个阶段起个名字。 然后,第二部分FROM用的我们上面构建的Tomcat镜像,COPY关键字增加了—from参数,用于拷贝某个阶段的文件到当前阶段。这样一个Dockerfile就都搞定了。

(4)小结

镜像小有很多好处,例如:

  • 快速部署;
  • 快速回滚, 减少服务中断时间;
  • 同时镜像仓库占用磁盘空间也少了。
4、DockerFile企业案例一

企业需求:启动Docker容器,同时开启Docker容器对外的22端口的监听,实现通过CRT或者Xshell登录。
编写Dockerfile文件:

# 设置基本的镜像,后续命令都以这个镜像为基础
FROM centos:v1
# 作者信息
MAINTAINER  wujincheng@163.com

# RUN命令会在上面指定的镜像里执行任何命令
RUN rpm --rebuilddb;yum install passwd openssl openssh-server -y
RUN echo '123456' | passwd --stdin root
RUN mkdir -p /root/.ssh && chown root.root /root && chmod 700 /root/.ssh

# 暴露ssh端口22
EXPOSE  22

# 设定运行镜像时的默认命令:输出ip,-D并以daemon方式启动sshd
CMD /usr/sbin/sshd -D;/bin/bash
5、DockerFile企业案例二

企业需求:开启SSH 6379端口,让Redis端口对外访问,Dockerfile内容如下:
编写Dockerfile文件:

# 设置基本的镜像,后续命令都以这个镜像为基础
FROM centos_lamp:v1 
# 作者信息
MAINTAINER  wujincheng@163.com

# RUN命令会在上面指定的镜像里执行任何命令
RUN rpm --rebuilddb;yum install redis* -y
RUN sed -i '/bind/127.0.0.1/0.0.0.0/g' /etc/redis.conf 

#暴露ssh端口6379
EXPOSE  6379

#-D设定运行以daemon方式启动sshd
CMD /usr/sbin/redis -D
6、DockerFile企业案例三

企业需求:基于Dockerfile开启Apache 80端口,并远程连接服务器
编写Dockerfile文件:

# 设置基本的镜像,后续命令都以这个镜像为基础
FROM centos_lamp:v1
# 作者信息
MAINTAINER  wujincheng@163.com

# RUN命令会在上面指定的镜像里执行任何命令
RUN rpm --rebuilddb;yum install pcre-devel -y
RUN rpm --rebuilddb;yum install httpd httpd-devel –y
RUN  echo “<h1>The Test Page JFEDU</h1>” >>/var/www/html/index.html

#暴露ssh端口80
EXPOSE 80

#启动httpd
CMD ["/usr/sbin/apachectl", "-D", "FOREGROUND"]
7、DockerFile企业案例四

企业需求:Docker虚拟化中,如何来构建我们的MYSQL数据库服务器呢?答案很简单,我们可以是dockerfile来生成mysql镜像并启动运行即可。
编写Dockerfile文件:

FROM centos:v1
RUN groupadd -r mysql && useradd -r -g mysql mysql
RUN rpm --rebuilddb;yum install -y gcc zlib-devel gd-devel
ENV MYSQL_MAJOR 5.6
ENV MYSQL_VERSION 5.6.20
RUN 
	&& curl -SL "http://dev.mysql.com/get/Downloads/MySQL-$MYSQL_MAJOR/mysql-$MYSQL_VERSION-linux-glibc2.5-x86_64.tar.gz" -o mysql.tar.gz \
	&& curl -SL "http://mysql.he.net/Downloads/MySQL-$MYSQL_MAJOR/mysql-$MYSQL_VERSION-linux-glibc2.5-x86_64.tar.gz.asc" -o mysql.tar.gz.asc \
	&& mkdir /usr/local/mysql \
	&& tar -xzf mysql.tar.gz -C /usr/local/mysql \
	&& rm mysql.tar.gz* \
ENV PATH $PATH:/usr/local/mysql/bin:/usr/local/mysql/scripts
WORKDIR /usr/local/mysql
VOLUME /var/lib/mysql
EXPOSE 3306
CMD ["mysqld", "--datadir=/var/lib/mysql", "--user=mysql"]
8、根据dockerfile生成镜像

用docker build根据Dockerfile创建镜像(centos:ssh):

#这种生成方式是用来指定名字不是Dockerfile的创建方式,-为占位符
docker  build  -t  [REPOSITORY]:[TAG]  -  <  /etc/dockerfile
#文件名默认为Dockerfile,所以不用指定,指定位置即可
docker  build  -t  [REPOSITORY]:[TAG]  .(指定位置为当前)
#注:-t是用来指定 Name and optionally a tag in the 'name:tag' format (default [])

在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凤求凰的博客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值