一、Docker镜像
1.1 镜像的概念
镜像是创建容器的基础。
镜像是一个只读的模板文件,里面包含运行容器中的应用程序所有需要的所有内容(应用程序文件、配置文件、运行库文件、依赖包等)。
1.2 镜像结构的分层
Docker 镜像由多个只读层组成,每个层都包含了文件系统的一部分。
这些层按照从底向上的顺序依次叠加,形成一个完整的镜像。
镜像的最底层是一个基础镜像(Base Image),上面叠加了一系列更高层的镜像,每个层都是前一个层的增量变化。
在容器启动时,Docker 引擎会将这些层通过联合文件系统合并成一个容器文件系统。
在容器运行过程中,Docker 引擎将修改操作写入一个可写层(Writeable Layer),该层仅保存容器运行时的状态和数据。
这种分层和联合文件系统的设计使得镜像的创建和传播非常高效,节省了存储空间和下载时间。
二、Docker镜像的创建
创建镜像有三种方法,分别为基于已有镜像创建、基于本地模板创建以及基于Dockerfile创建。
2.1 基于现有镜像创建
基于已有镜像创建主要使用 docker commit 命令。
本质上就是把一个容器里面运行的程序和该程序的运行环境打包,生成新的镜像。
#基本格式
docker commit [选项] 容器ID/名称 仓库名称:[标签]
##常用选项##
-m 说明信息;
-a 作者信息;
-p 生成过程中停止容器的运行。
2.1.1 创建思路
1)先用现有镜像创建启动容器 ,使用 docker run命令;
2)再进入容器进行内容更新 ,使用docker exec命令;
3)最后提交成新的镜像 ,使用 docker commit命令。
2.1.2 举个例子
首先启动一个镜像,在容器里做修改
docker create -it centos:7 /bin/bash
docker ps -a
然后将修改后的容器提交为新的镜像,需要使用该容器的 ID 号创建新镜像
docker commit -m "new" -a "centos" fb34a543fca2 centos:test
docker image
2.2 基于本地模板创建
通过导入操作系统模板文件生成镜像,模板可以从 OPENVZ 开源项目下载。
举个例子
#下载
wget http://download.openvz.org/template/precreated/debian-7.0-x86-minimal.tar.gz
#导入为镜像
cat debian-7.0-x86-minimal.tar.gz | docker import - debian:test
2.3 基于Dockerfile 创建
除了手动生成Docker镜像之外,可以使用Dockerfile自动生成镜像。
Dockerfile是由多条的指令组成的文件,其中每条指令对应 Linux 中的一条命令,Docker 程序将读取Dockerfile 中的指令生成指定镜像。
Dockerfile结构大致分为四个部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令。
Dockerfile每行支持一条指令,每条指令可携带多个参数,支持使用以“#“号开头的注释。
三、Dockerfile 详解
3.1 Dockerfile 操作指令
3.1.1 常用的操作指令
| 标题 | |
|---|---|
| 常用指令 | 含义 |
| FROM | 指定基础镜像(是Dockerfile的第一行指令) |
| MAINTAINER | 指定镜像维护人信息(可选) |
| RUN | 指定Linux命令,如果要执行连续多条命令时建议用 ; 或 && 或 <<EOF 串起来使用 |
| EXPOSE | 指定容器应用的端口 |
| ENV | 设置镜像的环境变量 |
| ADD/COPY | 复制文件/目录到镜像里 |
| VOLUME | 指定容器的匿名数据卷 |
| USER | 指定容器的运行用户 |
| WORKDIR | 指定后续镜像层的工作目录 |
| ARG | 指定构建镜像时传入的参数变量,docker build --build-arg 变量=值 |
| CMD/ENTRYPOINT | 指定容器启动时执行的命令 |
3.1.2 CMD和ENTRYPOINT的区别?
共同点:都可以用来指定容器启动命令。
区别:ENTRYPOINT指定的容器启动命令优先级更高。
如果CMD和ENTRYPOINT同时存在,那么CMD指定的内容将作为ENTRYPOINT指定的容器启动命令的选项或参数使用。
容器启动时运行的命令优先级
docker run --entrypoint=“命令” > 镜像里的ENTRYPOINT指定的命令 > docker run … 镜像 命令 > 镜像里的CMD指定的命令
3.1.3 ADD和COPY的区别?
共同点:都可以将本地的文件/目录复制到镜像里。
区别:ADD还可以通过URL下载文件复制到镜像里,还能将本地的压缩包解压后复制到镜像里。
URL下载和压缩包解压特性不能同时使用。
3.2 基于Dockerfile构建镜像的步骤
在编写 Dockerfile 时,有严格的格式需要遵循。
1)第一行 用FROM指令指明所用的基础镜像;
2)之后用MAINTAINER指令说明维护镜像的用户信息;
3)然后用镜像操作相关指令,比如RUN EXPOSE ENV ADD COPY 等指令,编写构建镜像的过程。每运行一条指令,都会给基础镜像添加新的一层;
4)结尾使用CMD/ENTRYPOINT指令指定容器启动时执行的命令;
5)最后使用docker build -t 新镜像名:标签 . [-f Dockerfile文件路径]命令构建镜像。
3.3 基于Dockerfile创建镜像应用实例
Step1 建立工作目录
mkdir /opt/apache
cd /opt/apache
Step2 创建并编写Dockerfile文件
vim Dockerfile
#基于的基础镜像
FROM centos:7
#维护镜像的用户信息
MAINTAINER this is apache image <hmj>
#镜像操作指令安装apache软件
RUN yum -y update
RUN yum -y install httpd
#开启 80 端口
EXPOSE 80
#复制网站首页文件
ADD index.html /var/www/html/index.html
- 准备网站页面
4.构建镜像
- 使用新镜像创建容器并运行
docker run -id --name apache1 -p 1314:80 httpd:centos
6.使用宿主机的ip与映射的端口号到浏览器进行访问测试
3.2 构建nginx的镜像
1.先创建一个工作目录
mkdir /opt/nginx
cd /opt/nginx
- 创建一个Dockerfile文件
vim Dockerfile
FROM centos:7
MAINTAINER this is nginx <lzq 20231020>
ADD nginx-1.22.0.tar.gz /opt/
RUN yum -y install pcre-devel zlib-devel openssl-devel gcc gcc-c++ make && \
useradd -M -s /sbin/nologin nginx && \
cd /opt/nginx-1.22.0 && \
./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_stub_status_module && \
make && \
make install
EXPOSE 80
EXPOSE 443
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]
3.进行创建镜像
docker build -t nginx:lzq .
4.如果碰到创建镜像发现yum安装依赖包时老报错根据下面的方式去解决问题
在/etc/resolv.conf文件下添加内容:
nameserver 8.8.8.8
nameserver 8.8.4.4
search localdomain
在/etc/sysctl.conf下添加内容:
net.ipv4.ip_forward = 1
并使用sysctl -p刷新
5.创建容器然后到浏览器上进行检测
docker run -id --name c1 -p 1314:80 nginx:yhy
3.3 构建tomcat镜像实例
1.按创建一个tomcat的工作目录
mkdir /opt/tomcat
cd /opt/tomcat/
2.现将安装包放在我们的工作目录中
3.编写dockerfile文件
vim dockerfile
FROM centos:7
ADD jdk-8u91-linux-x64.tar.gz /usr/local/
ENV JAVA_HOME /usr/local/jdk1.8.0_91
ENV JRE_HOME ${JAVA_HOME}/jre
ENV CLASSPATH .:${JAVA_HOME}/lib:${JRE_HOME}/lib
ENV PATH $JAVA_HOME/bin:$PATH
ADD apache-tomcat-9.0.16.tar.gz /usr/local/
EXPOSE 8080
CMD ["/usr/local/apache-tomcat-9.0.16/bin/catalina.sh", "run"]
4.创建我们的镜像
docker build -t tomcat:yhy .
5.创建容器去到我们的浏览器上进行测试
docker run -id --name c2 -p 1334:8080 tomcat:yhy
3.4如何减少nginx镜像的大小操作
我们会使用多结构的方式来进行减小镜像的大小
FROM centos:7 AS first
MAINTAINER this is nginx <lzq 20231020>
ADD nginx-1.22.0.tar.gz /opt/
RUN yum -y install pcre-devel zlib-devel gcc gcc-c++ make && \
useradd -M -s /sbin/nologin nginx && \
cd /opt/nginx-1.22.0 && \
./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_stub_status_module && \
make && \
make install
FROM centos:7
COPY --from=first /usr/local/nginx/ /usr/local/nginx/
RUN useradd -M -s /sbin/nologin nginx
EXPOSE 80
EXPOSE 443
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]
之后我们进行镜像的安装可以明显的看到大小少了不少
docker build -t nginx:lzq .
docker问题
1. 如何把我的镜像体积给缩小?
- 基础镜像尽量使用轻量级最小化的镜像。
- Dockerfile中尽量把RUN指令合并在一起,减少镜像的层数(因为每一个RUN指令就是一个镜像层)。
- 多级构建(拿Dockerfile构建好的镜像再构建一次)。
2.使用Dockerfile构建镜像分为几个步骤?
Dockerfile结构大致分为四个部分:基础镜像信息(用from指定)、维护者信息(maintainer、镜像操作指令和容器启动时执行指令。
-
第一行必须使用FROM指令指明所基于的镜像名称;
-
之后使用MAINTAINER 指令说明维护该镜像的用户信息;
-
然后是镜像操作相关指令,如RUN指令/EXPOSE/ADD/ENV/ARG等等。每运行一条指令,都会给基础镜像添加新的一层。(多条命令可以使用 ; 或 && 合并成一条命令,减少镜像的层数)
-
最后使用CMD或者ENTRYPOINT指令指定启动容器时要运行的命令操作。