目录
[1、 镜像的概念](#1、 镜像的概念)
[3、镜像容量过大的解决方案 :二层构建](#3、镜像容量过大的解决方案 :二层构建)
一、Docker镜像:
1、 镜像的概念
镜像是创建容器的基础。
镜像是一个只读的模板文件,里面包含运行容器中的应用程序所有需要的所有内容(应用程序文件、配置文件、运行库文件、依赖包等)。
2、docker的创建镜像方式:
1.1、基于已有镜像进行创建:
可以根据官方提供的镜像源创建镜像,然后拉起容器。是一个白白板,只能提供基础的功能,扩展性的功能还是需要自定义(进入容器操作)
1.2、基于模版创建:
通过导入操作系统模板文件可以生成镜像,模板可以从OPENVZ 开源项目下载
下载模版地址:Index of /template/precreated
模板里面就是使用docker export 命令导出的容器文件
导入为镜像,两种方法
cat debian-7.0-x86-minimal.tar.gz | docker import - debian:test #方法一
docker import debian-7.0-x86-minimal.tar.gz -- debian:test #方法二
查看镜像
docker images
使用导入的镜像创建容器
docker run -itd debian:test bash
docker ps -a
1.3、基于dockerfile创建:
生产中都是基于dockerfile
dockerfile:联合文件系统(UnionFS),docker镜像的基础,镜像通过分层来进行集成。
特性:一次同时加载多个文件系统,但是从外面来看,就是一个文件系统。
镜像加载的原理:docker镜像实际上就是由一层一层的文件系统组成,这种层级的文件系统就是UnionFS
每一层都是一个layers(层次),每一层都包含文件系统的一部分,这些层次叠加在一起,最终形成的就是RootFS
二、Dockerfile概述
1、Dockerfile概念:
dockerfile:创建镜像,创建自定义镜像
包括配置文件,挂载点,对外暴露的端口。设置环境变量
dockerfile的核心作用:
用户个性化定制docker的镜像
2、dockerfile分层:
bootfs:宿主机的引导文件系统,启动操作系统的文件,启动容器需要的最基本的文件。包含宿主机的bootloader和kernel。宿主机提供的内核和引导程序
rootfs:会给镜像自动创建一个操作系统。就是容器的操作系统,在dockerfile中,我们可以自己指定。rootfs是多个基础镜像和应用镜像结合起来的只读层。镜像实际上就是一个只读文件
容易基于镜像实例,运行起来之后,容器变成一个可读可写层
Docker镜像结构的分层
镜像不是一个单一的文件,而是有多层构成。容器其实是在镜像的最上面加了一层读写层,
在运行容器里做的任何文件改动,都会写到这个读写层。如果删除了容器,也就删除了其最上面的读写层,
文件改动也就丢失了。Docker使用存储驱动管理镜像每层内容及可读写层的容器层。
1、Dockerfile中的每个指令都会创建一个新的镜像层;
2、镜像层将被缓存和复用;
3、当Dockerfile的指令修改了,复制的文件变化了,或者构建镜像时指定的变量不同了,
对应的镜像层缓存就会失效;
4、某一层的镜像缓存失效,它之后的镜像层缓存都会失效;
5、镜像层是不可变的,如果在某一层中添加一个文件,然后在下一层中删除它,
则镜像中依然会包含该文件,只是这个文件在Docker 容器中不可见了。
3、dockerfile的结构:
- 基础镜像信息
- 维护者信息
- 镜像的操作指令
- 容器启动时,执行的命令
4、dockerfile的语法:
dockerfile中所有语法都是大写
FROM:指定基础镜像信息。指定容器的操作系统
MAINTAINER:指定维护者信息(可有可无)
RUN:在基础的镜像上执行的命令,每个RUN就是一层,分层越多,镜像就越大
ENTRYPOINT:设置容器运行时的默认命令(容器内部运行的主程序)
CMD:指定容器运行时的默认命令(docker run /bin/bash 后面加了其他命令。CMD的指令将会被覆盖。CMD后面不能加/bin/bash创建)
EXPOSE:暴露端口(指定容器的运行端口)
ENV:设置环境变量,环境变量可以被RUN命令使用(声明容器运行需要的环境变量)
ADD:复制,解压。解压不支持.zip和.rar格式。能解压tar.gz tar.bz2 支持url地址解压和复制(主要作用 解压)
COPY:复制文件,不能解压,只能复制本地文件。文件要和dockerfile在一个目录(官方推荐的复制命令)
VOLUME:创建一个容器内的挂载点,既可以为宿主机挂载,也可以实现容器与容器之间挂载
USER:设置运行镜像时使用的用户或者他的UID(可有可无,可以不加)
WORKDIR:为后续指令设置的工作目录
ONBUILD:这个镜像可以被其他镜像引用,需要这个命令。
ARG:传参,用于创建容器时,传递参数(可有可无)。ENV是容器运行时设置环境变量
5、CMD和ENTRYPOINT的区别
都是可以作为容器启动时的默认命令。
区别:
- CMD可以把参数传给ENTRYPOINT
- 有多个ENTRYPOINT和多个CMD,只会运行最后一个(一个dockerfile中只会有一个ENTRYPOINT和CMD)
- ENTRYPOINT的指令不会被覆盖,CMD的指令如果在docker run的后面加上输出,会被覆盖
- ENTRYPOINT和CMD的指令都是在容器启动时执行,都会成为容器的主进程。主进程负责接收信号,由主进程处理容器的生命周期,主进程一旦退出容器也将终止运行
6、COPY和ADD之间的区别:
共同点:COPY和ADD都可以把本地文件复制到镜像中,但是官方推荐如果是复制使用COPY
区别:
ADD可以解压,如果是一个压缩文件,ADD在复制之后会自动解压(tar.gz tar.bz2)可以支持URL下载源文件,只能支持下载,但是不能解压。通过URL拷贝的文件无法自动解压
COPY只能复制,不能解压,而且只能是本地文件,不支持URL路径
ADD 的优点: 在执行 <源文件> 为 tar 压缩文件的话,压缩格式为 gzip、bzip2 以及 xz 的情况下,会自动复制并解压到 <目标路径>。
ADD 的缺点: 在不解压的前提下,无法复制 tar 压缩文件。会令镜像构建缓存失效,
从而可能会令镜像构建变得比较缓慢。具体是否使用,可以根据是否需要自动解压来决定。
7、RUN命令的优化:
主要是减少镜像的层数,把多个RUN命令写在一块。
1、&&符号:
RUN yum -y install nginx && make -j 4 && make install
前一个命令自行成功才会执行下一个命令
2、;分号符号
RUN yum -y install nginx ; make -j 4 ; make install
不管前一个命令是否成功,后面的命令都会执行
3、|| 符号
RUN yum -y install nginx || make -j 4
如果前面的命令执行失败,才会执行后面的操作
4、\ 反斜杠符号
RUN yum -y install nginx \
&& make -j 4 \
&& make install
换行,提高可读性
三、基于Dockerfile创建镜像实例
Dockerfile创建镜像:
创建一个镜像,在镜像中自定义安装部署组件配置
1、基于Dockerfile构建镜像的步骤
在编写 Dockerfile 时,有严格的格式需要遵循。
1)第一行 用FROM指令指明所用的基础镜像;
2)之后用MAINTAINER指令说明维护镜像的用户信息;
3)然后用镜像操作相关指令,比如RUN EXPOSE ENV ADD COPY 等指令,编写构建镜像的过程。每运行一条指令,都会给基础镜像添加新的一层;
4)结尾使用CMD/ENTRYPOINT指令指定容器启动时执行的命令;
5)最后使用docker build -t 新镜像名:标签 . [-f Dockerfile文件路径]命令构建镜像。
2、构建一个httpd的dockerfile:
Dockerfile文件要和需要解压的文件在一个目录下
FROM centos:7
MAINTAINER this is my diy apache <dn>
RUN yum install -y gcc gcc-c++ make pcre pcre-devel expat-devel perl
ADD apr-1.6.2.tar.gz /opt/
ADD apr-util-1.6.0.tar.gz /opt/
ADD httpd-2.4.29.tar.bz2 /opt/
RUN mv /opt/apr-1.6.2 /opt/httpd-2.4.29/srclib/apr && mv /opt/apr-util-1.6.0 /opt/httpd-2.4.29/srclib/apr-util &&\
cd /opt/httpd-2.4.29/ &&\
./configure --prefix=/usr/local/httpd --enable-so --enable-rewrite --enable-charset-lite --enable-cgi &&\
make -j 4 && make install
EXPOSE 80
CMD ["/usr/local/httpd/bin/apachectl","-D","FOREGROUND"]
docker build -t apache:centos .
docker run -itd --name test1 -p 334:80 apache:centos
若yum安装错误,重启docker就行
3、镜像容量过大的解决方案 :二层构建
基础镜像尽量使用轻量级最小化的镜像。
Dockerfile中尽量把RUN指令合并在一起,减少镜像的层数(因为每一个RUN指令就是一个镜像层)。
多级构建(拿Dockerfile构建好的镜像再构建一次)。
二层构建(了解):压缩镜像大小
#基层镜像
FROM centos:7 AS first
#镜像作者信息描述
MAINTAINER this is apache image <yh 2022-11-23 >
#指定的Linu执行脚本
RUN yum -y install gcc gcc-c++ make pcre pcre-devel expat-devel perl
#将源码编译的安装包安放到容器中并进行解压
ADD apr-1.6.2.tar.gz /opt/
ADD apr-util-1.6.0.tar.gz /opt/
ADD httpd-2.4.29.tar.bz2 /opt/
#进行源码编译安装
RUN mv /opt/apr-1.6.2 /opt/httpd-2.4.29/srclib/apr && mv /opt/apr-util-1.6.0 /opt/httpd-2.4.29/srclib/apr-util && cd /opt/httpd-2.4.29 && ./configure --prefix=/usr/local/httpd --enable-so --enable-rewrite --enable-charset-lite --enable-cgi && make -j 4 && make install
#二阶段构建
FROM centos:7
#将一阶段的已安装好的包安防到二阶端中,并舍弃一阶段的其他无用资源
COPY --from=first /usr/local/httpd /usr/local/httpd
#安装apache运行所需的环境依赖包,不再安装源码编译所需的依赖包
RUN yum install -y pcre pcre-devel expat-devel perl
EXPOSE 80
ENTRYPOINT ["/usr/local/httpd/bin/apachectl","-D","FOREGROUND"]
docker build -t apache1:centos .
4、构建一个nginx的dockerfile:
Dockerfile:
FROM centos:7
MAINTAINER "this is nginx <koeda>"
RUN yum -y install gcc pcre-devel openssl-devel zlib-devel openssl openssl-nginx
ADD nginx-1.22.0.tar.gz /opt
RUN useradd -M -s /sbin/nologin nginx
RUN cd /opt/nginx-1.22.0/ &&\
./configure --prefix=/usr/local/nginx \
--user=nginx \
--group=nginx \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_realip_module \
--with-http_stub_status_module \
--with-http_gzip_static_module \
--with-pcre \
--with-stream \
--with-stream_ssl_module \
--with-stream_realip_module &&\
make && make install &&\
chown -R nginx.nginx /usr/local/nginx &&\
ln -s /usr/local/nginx/sbin/nginx /usr/sbin/ &&\
echo "[Unit] \
Description=nginx - high performance web server \
Documentation=http://nginx.org/en/docs/ \
After=network-online.target remote-fs.target nss-lookup.target \
Wants=network-online.target \
[Service] \
Type=forking \
PIDFile=/usr/local/nginx/run/nginx.pid \
ExecStart=/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf \
ExecReload=/bin/kill -s HUP $MAINPID \
ExecStop=/bin/kill -s TERM $MAINPID \
[Install] \
WantedBy=multi-user.target" > /lib/systemd/system/nginx.service &&\
mkdir -p /usr/local/nginx/run/ &&\
sed '/#pid/c pid /usr/local/nginx/run/nginx.pid;' /usr/local/nginx/conf/nginx.conf &&\
echo "this is nginx:docker" > /usr/local/nginx/html/index.html &&\
/usr/local/nginx/sbin/nginx
EXPOSE 80
CMD ["nginx","-g","daemon off;"]
docker build -t nginx:centos .
docker run -itd --name test1 -p 888:80 nginx:centos