Docker的镜像制作
Docker的镜像制作1.1 镜像的基本原理
Docker 的镜像是创建容器的底子,就是一个普通文件,是一个面向 Docker 容器的只读模板。其实镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开辟的软件,它包含运行某个软件所需的全部内容(包括代码、运行时、库、环境变量和配置文件),这个打包好的运行环境就是image镜像文件。
比方:一个镜像可以是一个完备的 CentOS 操作系统环境,称为一个 CentOS 镜像;也可以是一个安装了 MySQL 的应用步伐,称之为一个 MySQL 镜像等等。镜像是一个静态的概念,不包含任何动态数据,其内容在构建之后也不会被改变。
1、镜像的底层加载原理
Docker 的镜像实际上由一层一层的文件系统构成,这种层级的文件系统 UnionFS(联合文件系统)。
UnionFS:是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将差别目录挂载到同一个假造文件系统下(unite several directories into a single virtual filesystem)。Union 文件系统是 Docker 镜像的底子。镜像可以通过分层来进行继承,基于底子镜像(没有父镜像),可以制作各种具体的应用镜像。
2、镜像的结构
镜像不是一个单一的文件,而是有多层构成。可以通过 docker history 镜像 命令查察镜像中各层内容及巨细,每层对应着 Dockerfile 中的一条指令。
Docker 镜像默认存储在 /var/lib/docker 目录中 。容器其实是在镜像的最上面加了一层读写层, 在运行容器里做的任何文件改动,都会写到这个读写层。假如删除了容器,也就删除了其最上面的读写层,文件改动也就丢失了。Docker 利用存储驱动管理镜像每层内容及可读写层的容器层。
1、分层结构的特点
其实我们也会思量 Docker 为什么会才用这种分层的结果,它有什么利益呢?最大的一个利益就是共享资源。
比如:有多个镜像都从相同的 base 镜像构建而来,那么宿主机只需在磁盘上生存一份 base 镜像,同时内存中也只需加载一份 base 镜像,就可以为全部容器服务了。而且镜像的每一层都可以被共享。
2、分层结构的特点
Docker 镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部,这一层通常被称为容器层,容器层之下的都叫镜像层。
https://i-blog.csdnimg.cn/direct/c34225eff99e49dd8a098bf45b582367.png
3、镜像的制作方式
[*]基于容器创建镜像
基于现有容器创建主要利用 docker commit 命令,就是把一个容器里面运行的步伐以及该步伐的运行环境打包起来生成新的镜像。
它的缺点是:在底子镜像之上做的操作不会记录,别人不知道做了哪些操作,因此被称为黑盒镜像。
docker commit [选项] 容器ID/名称 生成的镜像:[标签]
-m:说明信息;
-a:作者信息;
-p:生成过程中停止容器的运行;
# 示例
# docker run -d --name web1 nginx:latest //创建一个容器
# docker ps -a //查看运行状态
# docker commit web1 nginx:v1 //生成镜像,生成之前先在容器里写点东西
# docker images //查看生成的镜像
# docker run -itd -p 80:80 --name web2 nginx:v1 //用生成的镜像创建容器
[*]基于Dockerfile创建常用底子服务
除了手动生成 Docker 镜像之外,可以利用 Dockerfile 主动生成镜像。Dockerfile 是由一组指令构成的文件,其中每条指令对应 Linux 中的一条命令,Docker 步伐将读取Dockerfile 中 的指令生成指定镜像。
1.2 Dockerfile制作镜像
镜像的制作实际上就是定制每一层所添加的配置、文件等信息。但是命令究竟只是命令,每次定制都得去重复执行这个命令,而且还不敷直观,假如我们可以把每一层修改、安装、构建、操作的命令都写入一个脚本,用这个脚原来构建、定制镜像。这个脚本就是我们说的 Dockerfile
Dockerfile 是一个文本文件,其内包含了一条条的指令 (Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。
1、Dockerfile常用指令
Dockerfile 结构大致分为四个部门:底子镜像信息、维护者信息、镜像操作指令 和 容器启动时执行指令。Dockerfile 文件每行支持一条指令,每条指令可携带多个参数,每运行一条指令,都会给底子镜像添加新的一层。
https://i-blog.csdnimg.cn/direct/751f06c47c1e440c9d8be4be814ab0b6.png#pic_center
指令解释FROM 镜像指定底子镜像(新镜像所基于的镜像),第一条指令必须为 FROM 指令,每创建一个镜像就需要一条 FROM 指令。MAINTAINER 名字阐明新镜像的维护人信息(可以不写)RUN 命令在所基于的镜像上执行命令,并提交到新的镜像中CMD [“命令”,“参数”]指令启动容器时默认要运行的命令或者脚本,假如指定多条则只能最后一条被执行(假如在启动容器时指定命令,则不起作用)EXPOSE 端标语指定新镜像加载到 Docker 时要开启的端口(只是定义,不更改)ENV 环境变量 变量值设置一个环境变量的值,会被后面的 RUN 利用ADD 源 目标将宿主机文件拷贝到容器里面去,源文件要与 Dockerfile 文件在相同目录中(源文件是压缩包会主动解压)COPY 源 目标将本田主机上的文件或目录复制到容器里,源文件要与 Dockerfile 文件在相同的目录中VOLUME [“目录”]在容器中创建一个挂载点(主动创建匿名卷)USER 用户名/UID指定运行容器时的用户WORKDIR 路径为后续的 RUN、CMD、ENTRYPOINT 指定工作目录ONBUILD 命令指定所生成的镜像作为一个底子镜像时所要运行的命令HEALTHCHECK健康检查,定义检查指令 2、Dockerfile制作镜像:案例
[*]构建Nginx镜像
# docker tag hub.atomgit.com/amd64/centos:centos7 centos:7 //下载centos镜像,并修改标签
# mkdir nginx;cd nginx
# vim Dockerfile
FROM centos:7
RUN sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/* && \
sed -i 's/mirror.centos.org/vault.centos.org/g' /etc/yum.repos.d/* && \
sed -i 's/#baseurl=/baseurl=/g' /etc/yum.repos.d/* && \
yum -y install gcc make pcre-devel zlib-devel tar zlib
ADD nginx-1.12.0.tar.gz /usr/src/
RUN cd /usr/src/nginx-1.12.0 && \
mkdir -p /usr/local/nginx && \
./configure --prefix=/usr/local/nginx && \
make && make install && \
ln -s /usr/local/nginx/sbin/* /usr/local/sbin/
RUN rm -rf /usr/src/nginx-1.12.0
EXPOSE 80
EXPOSE 443
CMD ["nginx","-g","daemon off;"]
# ls //将nginx源码包拉上来
Dockerfilenginx-1.12.0.tar.gz
# docker build -t 镜像:tag . //构建镜像,要注意要在有Dockerfile文件的目录执行
[*]构建LNMP镜像
# mkdir lnmp;cd lnmp
# vim Dockerfile
FROM centos:7
# 安装ngix
RUN rm -f /etc/yum.repos.d/* && \
curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo && \
yum -y install epel-release && \
yum clean all && \
yum makecache && \
yum -y install nginx
RUN sed -i '/^user/s/nginx/nginx\ nginx/g' /etc/nginx/nginx.conf
COPY default.conf /etc/nginx/conf.d/default.conf
# 安装mariadb和php
RUN yum -y install mariadb-server mariadb-devel mariadb php-mysql php php-fpm
# 修改php-fpm配置文件
RUN sed -i '/^user/s/apache/nginx/g' /etc/php-fpm.d/www.conf && \
sed -i '/^group/s/apache/nginx/g' /etc/php-fpm.d/www.conf
# 声明mariadb的用户名和密码
ENV MARIADB_USER=root
ENV MARIADB_PASS=123456
# 支持中文
ENV LC_ALL=en_US.UTF-8
# 添加并运行脚本
ADD db_init.sh /root/db_init.sh
RUN chmod 775 /root/db_init.sh
RUN /root/db_init.sh
ADD run.sh /root/run.sh
RUN chmod 775 /root/run.sh
ADD index.php /usr/share/nginx/html/index.php
# 开放的端口
EXPOSE 80
EXPOSE 3306
EXPOSE 443
EXPOSE 9000
# 每次创建容器运行此脚本
CMD ["/root/run.sh"]
# vim default.conf
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.php index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
location ~ \.php$ {
root html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /usr/share/nginx/html$fastcgi_script_name;
include fastcgi_params;
}
}
# vim db_init.sh //数据库初始化脚本
#!/bin/bash
#初始化数据库命令
mysql_install_db --user=mysql
sleep 3
#启动数据库
mysqld_safe &
sleep 3
# 涉及到的变量在 Dockerfile 中都已经声明
mysqladmin -u "$MARIADB_USER" password "$MARIADB_PASS"
# 授权命令
mysql -u"$MARIADB_USER" -p"$MARIADB_PASS" -e "use mysql; grant all privileges on *.* to '$MARIADB_USER'@'%' identified by '$MARIADB_PASS' with grant option;"
mysql -u"$MARIADB_USER" -p"$MARIADB_PASS" -e "grant all privileges on *.* to '$MARIADB_USER'@'localhost' identified by '$MARIADB_PASS';"
h=$(hostname)
mysql -u"$MARIADB_USER" -p"$MARIADB_PASS" -e "use mysql; update user set password=password('$MARIADB_PASS') where user='$MARIADB_USER' and host='$h';"
# vim run.sh //服务启动脚本
#!/bin/bash
mysqld_safe &
/usr/sbin/nginx &
/usr/sbin/php-fpm
# vim index.php
<?php
echo date("Y-m-d H:i:s")."<br />\n";
$link=mysql_connect("localhost","root","123456");
if(!$link) echo "FAILD!";
else echo "MySQL is OK!";
phpinfo();
?>
# docker build -t centos:lnmp .
# docker run -d --name lnmp -P centos:lnmp
1.3 多阶段构建镜像
在 Docker 17 版本后提供的,利用多阶段构建可以在一个 Dockerfile 中利用多个 FROM 语句。每个FROM指令都可以利用差别的底子镜像,并表示开始一个新的构建阶段。你可以很方便的将一个阶段的文件复制到另一个阶段,在终极的镜像中留下你需要的内容。
利用多阶段构建的利益:
1.减小镜像巨细:每个构建阶段只包含必要的依靠项和文件,从而减小了生成的镜像巨细。这可以减少镜像的存储空间和传输时间。
2.提高构建速度:每个构建阶段可以一起执行。而且,每个构建阶段只构建所需的内容,从而减少了构建时间。
3.简化 Dockerfile:利用多个构建阶段可以将 Dockerfile 分解为更小的部门,从而使Dockerfile 更加易于管理和维护。
4.提高安全性:利用多个构建阶段可以限定敏感信息的泄露。比方,在第一个构建阶段中,可以包含敏感信息,比方私有密钥或密码。而在第二个构建阶段中,可以只包含必要的文件和依靠项
➤ 多阶段构建案例(未利用多阶段构建)
# mkdir demo;cd demo
# vim demo.c
# include<stdio.h>
int main()
{
printf("%s\n","This is a demo!");
return 0;
}
# vim Dockerfile
FROM centos:7
ENV version=1.0
WORKDIR /demo
COPY demo.c .
RUN curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo && \
yum -y install gcc && \
gcc -v
RUN gcc demo.c -o demo && \
rm -rf demo.c && \
yum -y remove gcc && \
cp demo /usr/local/bin/
CMD ["demo"]
# docker build -t demo:v1 .
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
demo v1 d05f8303b0bc 22 seconds ago 557MB
➤ 多阶段构建案例(利用多阶段构建)
# vim Dockerfile //基于上面的未使用构建,添加这两行
FROM centos:7
ENV version=1.0
WORKDIR /demo
COPY demo.c .
RUN curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo && \
yum -y install gcc && \
gcc -v
RUN gcc demo.c -o demo && \
rm -rf demo.c && \
yum -y remove gcc && \
cp demo /usr/local/bin/
FROM centos:7
# --from表示从其他阶段拷贝内容到本阶段,0表示从第一个阶段拷贝到本阶段
COPY --from=0 /usr/local/bin/demo /usr/local/bin/demo
CMD ["demo"]
# docker build -t demo:v1 .
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
demo v2 68bc7352dcfa 13 seconds ago 204MB //使用多阶段构建
demo v1 d05f8303b0bc 9 minutes ago 557MB //未使用多阶段构建
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]