由于Docker官网公共仓库镜像大多不完整,无法真正满足企业的生产环境系统,此时需要我们自行定制镜像或者重新打包镜像。Docker镜像制作是管理员的必备工作之一,Docker镜像制作的方法主要有两种,制作方法如下:
- Docker commit|export将新容器提交至Images列表;
- 编写Dockerfile,bulid新的镜像至镜像列表;
文章目录
- 一、commit方式
- 二、Export方式
- 三、Dockerfile企业级制作方法(推荐)
- 1、Dockerfile制作原理
- 2、如下为DockerFile制作镜像,必备的指令和参数的详解:
- 3、编写DockerFile最佳实践
- (1)减少镜像层
- (2)优化镜像大小:清理无用数据
- (3)减少网络传输时间
- (4)多阶段进行镜像构建
- (4)小结
- 4、DockerFile企业案例一
- 5、DockerFile企业案例二
- 6、DockerFile企业案例三
- 7、DockerFile企业案例四
- 8、根据dockerfile生成镜像
一、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 ps
docker export c432b9da999c(容器ID) >/root/centos-v3.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 [])