当前位置: 首页 > news >正文

Dockerfile容器镜像构建技术

文章目录

  • 1、容器回顾
    • 1_容器与容器镜像之间的关系
    • 2_容器镜像分类
    • 3_容器镜像获取的方法
  • 2、其他容器镜像获取方法演示
    • 1_在DockerHub直接下载
    • 2_把操作系统的文件系统打包为容器镜像
    • 3_把正在运行的容器打包为容器镜像
  • 3、Dockerfile介绍
  • 4、Dockerfile指令
    • 1_FROM
    • 2_RUN
    • 3_CMD
    • 4_EXPOSE
    • 5_ENV
    • 6_ADD
    • 7_COPY
    • 8_ENTRYPOINT
    • 9_VOLUME
    • 10_USER
    • 11_WORKDIR
  • 5、Dockerfile基本构成
  • 6、Dockerfile生成容器镜像方法
  • 7、Dockerfile生成容器镜像案例
    • 1_使用Dockerfile生成容器镜像步骤
    • 2_使用Dockerfile生成Nginx容器镜像
    • 3_使用Dockerfile生成Tomcat容器镜像
  • 8、使用Dockerfile生成容器镜像优化
    • 1_减少镜像分层
    • 2_清理无用数据
    • 3_多阶段构建镜像
    • 4_构建出现问题

1、容器回顾

1_容器与容器镜像之间的关系

说到Docker管理的容器不得不说容器镜像,主要因为容器镜像是容器模板,通过容器镜像我们才能快速创建容器。

如下图所示:

在这里插入图片描述

Docker Daemon 通过容器镜像创建容器。


2_容器镜像分类

操作系统类

  • CentOS

  • Ubuntu

  • 在 Docker Hub下载或自行制作

应用类

  • Tomcat

  • Nginx

  • MySQL

  • Redis


3_容器镜像获取的方法

主要有以下几种:

1、在 DockerHub 直接下载

2、把操作系统中的文件系统打包为容器镜像

3、把正在运行的容器打包为容器镜像,即docker commit

4、通过Dockerfile实现容器镜像的自定义及生成


2、其他容器镜像获取方法演示

1_在DockerHub直接下载

拉取系统镜像

docker pull centos:latest

拉取应用镜像

docker pull nginx:latest

2_把操作系统的文件系统打包为容器镜像

1.安装一个最化的操作系统

在这里插入图片描述

系统1核1g内存20g就行,只是用来做镜像不需要太高配置,最小安装也可以不创建其他用户,只设个root密码就行。


2.把操作系统中文件系统进行打包

在这里插入图片描述

在无图形化操作系统中输入如下命令

tar --numeric-owner --exclude=/proc --exclude=/sys -cvf centos7u6.tar /

--numeric-owner:这个选项让 tar 在归档时使用用户和组的数字 ID(UID 和 GID),而不是使用用户名和组名。


3.把打包后文件加载至本地文件系统生成本地容器镜像

传输到另一主机中

[root@localhost ~]# scp centos7u6.tar 192.168.150.145:/root
The authenticity of host '192.168.150.145 (192.168.150.145)' can't be established.
ECDSA key fingerprint is SHA256:AZAtK8Y0RYrW8aImRua0toxovVYNzIxo/vwF55SNq4Y.
ECDSA key fingerprint is MD5:25:78:36:4f:e3:8f:20:a4:03:2b:b2:47:d8:39:e5:f6.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.150.145' (ECDSA) to the list of known hosts.
root@192.168.150.145's password: 
centos7u6.tar

查看打包的文件大小

[root@localhost ~]# ls -lh
总用量 1.3G
-rw-r--r--. 1 root root 1.3G 12月  6 10:58 centos7u6.tar

导入自定义镜像

docker import centos7u6.tar centos7u6:v1

查看自定义镜像

[root@localhost ~]# docker images
REPOSITORY                        TAG          IMAGE ID       CREATED          SIZE
centos7u6                         v1           b533c3b8dd48   28 seconds ago   1.34GB

使用自定义镜像运行容器

[root@localhost ~]# docker run -it centos7u6:v1 bash
[root@44b68ccd0b89 /]# ip route
default via 172.17.0.1 dev eth0 
172.17.0.0/16 dev eth0 proto kernel scope link src 172.17.0.2 

3_把正在运行的容器打包为容器镜像

1.运行一个容器

运行之前创建的容器并进入其内部

docker start 44b68ccd0b89
docker exec -it 44b68ccd0b89 /bin/bash

2.在容器中安装应用

由于 CentOS7 官方 yum 源不维护了,先导入阿里镜像源再安装软件

[root@44b68ccd0b89 /]# curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
[root@44b68ccd0b89 /]# yum -y install httpd

3.把正在运行的容器打包为容器镜像

使用让容器继续运行的方式退出

[root@44b68ccd0b89 /]# ctrl + p +q

将容器提交为镜像

docker commit 44b68ccd0b89 centos7u6-httpd:v1

查看创建的镜像

[root@localhost ~]# docker images
REPOSITORY                        TAG          IMAGE ID       CREATED          SIZE
centos7u6-httpd                   v1           bb155ef55e50   22 seconds ago   1.91GB

发现使用该镜像创建的容器中有我们下载的软件

[root@localhost ~]# docker run -it centos7u6-httpd:v1 bash
[root@a54843b01bb0 /]# rpm -qa | grep httpd
httpd-tools-2.4.6-99.el7.centos.1.x86_64
httpd-2.4.6-99.el7.centos.1.x86_64

3、Dockerfile介绍

Dockerfile 是一种能够被 Docker 程序解释的剧本。

Dockerfile 由一条一条的指令组成,并且有自己的书写格式和支持的命令。

当我们需要在容器镜像中指定自己额外的需求时,只需在 Dockerfile 上添加或修改指令,然后通过docker build生成我们自定义的容器镜像(image)。

在这里插入图片描述


4、Dockerfile指令

构建类指令

  • 用于构建 image
  • 其指定的操作不会在运行image的容器上执行(FROM、MAINTAINER、RUN、ENV、ADD、COPY)

设置类指令

  • 用于设置image的属性
  • 其指定的操作将在运行image的容器中执行(CMD、ENTRYPOINT、USER 、EXPOSE、VOLUME、WORKDIR、ONBUILD)

每一个指令都会形成一层Layer,指令说明:

指令描述
FROM构建新镜像基于的基础镜像
LABEL标签
RUN构建镜像时运行的 Shell 命令
COPY拷贝文件或目录到镜像中
ADD解压压缩包并拷贝
ENV设置环境变量
USER为 RUN、CMD 和 ENTRYPOINT 执行命令指定运行用户
EXPOSE声明容器运行的服务端口
CMD运行容器时默认执行,如果有多个CMD指令,最后一个生效
ENTRYPOINT镜像中应用的启动命令,容器运行时调用
WORKDIR为 RUN、CMD、ENTRYPOINT、COPY 和 ADD 设置工作目录
VOLUME创建一个挂载点(mount point),并将其作为一个持久化数据卷(volume)来使用
MAINTAINER指定镜像的维护者信息,已经被废弃,推荐使用LABEL。

指令详细解释,参考官网:https://docs.docker.com/reference/dockerfile/

通过man dockerfile也可以查看到详细的说明,这里简单的翻译并列出常用的指令


1_FROM

FROM 指令用于指定其后构建新镜像所使用的基础镜像。

FROM 指令必是 Dockerfile 文件中的首条命令。

FROM 指令指定的基础image可以是官方远程仓库中的,也可以位于本地仓库,优先本地仓库。

  • 格式:FROM <image>:<tag>

例:

FROM centos:latest

2_RUN

RUN 指令用于在构建镜像中执行命令,有以下两种格式:

  • shell 格式:RUN <命令>

例:

RUN echo 'run duration' > /var/www/html/index.html
  • exec 格式:RUN ["可执行文件", "参数1", "参数2"]

例:

RUN ["/bin/bash", "-c", "echo hello world > /var/www/html/index.html"]

注意:

按优化的角度来讲,当有多条要执行的命令,不要使用多条 RUN,尽量使用&&符号与\符号连接成一行。

因为多条 RUN 命令会让镜像建立多层(总之就是会变得臃肿了😃)

RUN yum install httpd httpd-devel -y
RUN echo test > /var/www/html/index.html

可以改成

RUN yum install httpd httpd-devel -y && echo test > /var/www/html/index.html

或者改成

RUN yum install httpd httpd-devel -y  \&& echo test > /var/www/html/index.html

3_CMD

CMD与RUN不同,CMD用于指定在容器启动时所要执行的命令,而RUN用于指定镜像构建时所要执行的命令。

格式有三种:

CMD ["executable","param1","param2"]
CMD ["param1","param2"]
CMD command param1 param2

每个 Dockerfile 只能有一条 CMD 命令,如果指定了多条命令,只有最后一条会被执行。

如果用户启动容器时候指定了运行的命令,则会覆盖掉CMD指定的命令。

什么是启动容器时指定运行的命令?

docker run -d -p 80:80 image_name commond_run

4_EXPOSE

EXPOSE 指令用于指定容器在运行时监听的端口

  • 格式:EXPOSE <port> [<port>...]

例:

EXPOSE 80 3306 8080

上述运行的端口还需要使用docker run运行容器时通过-p参数映射到宿主机的端口。


5_ENV

ENV 指令用于指定一个环境变量

  • 格式:ENV <key> <value> 或者 ENV <key>=<value>

例:

ENV JAVA_HOME /usr/local/jdkxxxx/

6_ADD

ADD 指令用于把宿主机上的文件拷贝到镜像中

  • 格式:ADD <src> <dest>

<src>可以是一个本地文件或本地压缩文件,还可以是一个url,如果把<src>写成一个url,那么ADD就类似于wget命令,<dest>路径的填写可以是容器内的绝对路径,也可以是相对于工作目录的相对路径。


7_COPY

COPY 指令与 ADD 指令类似,但 COPY 的源文件只能是本地文件

格式:

COPY <src> <dest>

8_ENTRYPOINT

ENTRYPOINT 与 CMD 非常类似

相同点:

  • 都是容器启动时才运行
  • 一个 Dockerfile 只写一条,如果写了多条,那么只有最后一条生效

不同点:

  • 如果用户启动容器时候指定了运行的命令,ENTRYPOINT 不会被运行的命令覆盖,而 CMD 则会被覆盖

格式有两种:

ENTRYPOINT ["executable", "param1", "param2"]
ENTRYPOINT command param1 param2

9_VOLUME

VOLUME 指令用于把宿主机里的目录与容器里的目录映射

只指定挂载点,docker 宿主机映射的目录为自动生成的。

格式:

VOLUME ["<mountpoint>"]

10_USER

USER 指令设置启动容器的用户(像hadoop需要hadoop用户操作,oracle需要oracle用户操作)

可以是用户名或 UID

USER daemon
USER 1001

注意

如果设置了容器以daemon用户去运行,那么 RUN、CMD 和 ENTRYPOINT 都会以这个用户去运行

镜像构建完成后,通过docker run运行容器时,可以通过-u参数来覆盖所指定的用户


11_WORKDIR

WORKDIR 指令设置工作目录,类似于cd命令。不建议使用RUN cd /root,建议使用 WORKDIR

WORKDIR /root

Docker 镜像的每一层的默认工作目录是/(根目录),除非通过 WORKDIR 指令显式改变,cd不能跨层级生效。


5、Dockerfile基本构成

组成说明示例
基础镜像信息定义容器的基础镜像,通常使用 FROM 指令指定。
基础镜像可以是官方的镜像,或者自定义的镜像。
FROM centos:7
维护者信息通过 LABELMAINTAINER 指令定义镜像的维护者信息,通常包括姓名和联系方式。LABEL maintainer="sy@163.com"
MAINTAINER "sy@163.com"
镜像操作指令用来安装软件、配置环境等。
常见指令有 RUNCOPYADDWORKDIRENV 等。
RUN yum install -y wget
COPY ./app /usr/local/app
WORKDIR /usr/local/app
容器启动时执行指令定义容器启动后执行的命令。
通常使用 CMDENTRYPOINT 指令,CMD 是默认命令,ENTRYPOINT 可以提供可执行文件及其参数。
CMD ["java", "-jar", "app.jar"]
ENTRYPOINT ["python3", "app.py"]

6、Dockerfile生成容器镜像方法

在这里插入图片描述


7、Dockerfile生成容器镜像案例

1_使用Dockerfile生成容器镜像步骤

第一步:创建一个文件夹(目录)

第二步:在文件夹(目录)中创建 Dockerfile 文件(并编写)及其它文件

第三步:使用docker build命令构建镜像

第四步:使用构建的镜像启动容器


2_使用Dockerfile生成Nginx容器镜像

在新的目录下进行操作

mkdir nginxroot
cd nginxroot

配置 nginx 首页的内容

echo "nginx's running" >> index.html

编写 Dockerfile 文件,就叫这个名字,不然需要单独指定

vim Dockerfile

并添加如下内容

# 指定基础镜像
FROM centos:centos7
# 指定镜像维护者信息,等于MAINTAINER "sy<sy@163.com>"已被弃用
LABEL maintainer="sy<sy@163.com>"
# 由于centos7官方不再维护yum源,所以设置阿里仓库地址,CentOSBase提供CentOS系统基础的包
RUN curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
# 下载wget命令
RUN yum -y install wget
# 设置 EPEL 源, EPEL 提供额外的社区支持的包
RUN wget -O /etc/yum.repos.d/epel.repo https://mirrors.aliyun.com/repo/epel-7.repo
# 安装 nginx
RUN yum -y install nginx
# 设置主页内容
ADD index.html /usr/share/nginx/html/
# 使nginx不以守护进程(后台)模式运行,这样容器才不会立刻退出
RUN echo "daemon off;" >> /etc/nginx/nginx.conf
# 暴露容器的 80 端口
EXPOSE 80
# 启动 nginx,等同于CMD /usr/sbin/nginx,推荐使用
CMD ["/usr/sbin/nginx"]

使用docker build命令构建镜像

  • -t:全称是tag,表示版本
  • 镜像组成格式:repository:version
  • .:表示当前目录下的Dockerfile文件,不这么写则使用-f指定Dockerfile文件
docker build -t centos7-nginx:v1 .

输出:

 => [internal] load build definition from Dockerfile                                                                                                                                                          0.0s=> => transferring dockerfile: 986B                                                                                                                                                                          0.0s=> [internal] load metadata for docker.io/library/centos:centos7                                                                                                                                             4.4s=> [internal] load .dockerignore                                                                                                                                                                             0.0s=> => transferring context: 2B                                                                                                                                                                               0.0s=> [1/7] FROM docker.io/library/centos:centos7@sha256:be65f488b7764ad3638f236b7b515b3678369a5124c47b8d32916d6487418ea4                                                                                       0.0s=> [internal] load build context                                                                                                                                                                             0.0s=> => transferring context: 91B                                                                                                                                                                              0.0s=> CACHED [2/7] RUN curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo                                                                                                  0.0s=> CACHED [3/7] RUN yum -y install wget                                                                                                                                                                      0.0s=> CACHED [4/7] RUN wget -O /etc/yum.repos.d/epel.repo https://mirrors.aliyun.com/repo/epel-7.repo                                                                                                           0.0s=> CACHED [5/7] RUN yum -y install nginx                                                                                                                                                                     0.0s=> CACHED [6/7] ADD index.html /usr/share/nginx/html/                                                                                                                                                        0.0s=> CACHED [7/7] RUN echo "daemon off;" >> /etc/nginx/nginx.conf                                                                                                                                              0.0s=> exporting to image                                                                                                                                                                                        0.0s=> => exporting layers                                                                                                                                                                                       0.0s=> => writing image sha256:16b8feb631a0952739150342851e9244b34383c7c39f17d93d985b352e47fc78                                                                                                                  0.0s=> => naming to docker.io/library/centos7-nginx:v1

查看构建的镜像

[root@localhost nginxroot]# docker images
REPOSITORY                        TAG          IMAGE ID       CREATED         SIZE
centos7-nginx                     v1           16b8feb631a0   9 minutes ago   757MB

运行容器

docker run -d -p 8081:80 centos7-nginx:v1

测试

[root@localhost nginxroot]# curl http://localhost:8081
nginx's running

3_使用Dockerfile生成Tomcat容器镜像

创建工作目录

mkdir tomcatdir
cd tomcatdir/

配置 tomcat 首页内容

echo "tomcat is running" >> index.html

准备存放jdk的文件目录(root目录有一个jdk11的安装包)

tar xf /root/jdk-11.0.25_linux-x64_bin.tar.gz -C /root/tomcatdir/
mv /root/tomcatdir/jdk-11.0.25 /root/tomcatdir/jdk

编写 Dockerfile 文件

vim Dockerfile

添加如下内容,如果 tomcat 无法下载,在此链接中查看存在的 Tomcat 版本,替换下方 BIG_VERSION 和 VERSION 对应的值即可

# 容器的基础镜像
FROM centos:centos7
# 指定镜像维护者信息
LABEL maintainer="sy<sy@163.com>"
# 设置相关的环境变量
ENV BIG_VERSION=9
ENV VERSION=9.0.97
ENV JAVA_HOME=/usr/local/jdk
ENV TOMCAT_HOME=/usr/local/tomcat
# 设置阿里yum源
RUN curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
# 安装wget
RUN yum -y install wget
# 下载tomcat
RUN wget https://dlcdn.apache.org/tomcat/tomcat-${BIG_VERSION}/v${VERSION}/bin/apache-tomcat-${VERSION}.tar.gz
# 解压
RUN tar xf apache-tomcat-${VERSION}.tar.gz
# 重命名
RUN mv apache-tomcat-${VERSION} /usr/local/tomcat
# 删除tomcat的安装包,节省空间
RUN rm -rf apache-tomcat-${VERSION}.tar.gz /usr/local/tomcat/webapps/*
# 创建根目录
RUN mkdir /usr/local/tomcat/webapps/ROOT
# 添加tomcat访问首页
ADD ./index.html /usr/local/tomcat/webapps/ROOT/
# 添加jdk
ADD ./jdk /usr/local/jdk
# 配置相关环境变量
RUN echo "export TOMCAT_HOME=/usr/local/tomcat" >> /etc/profile
RUN echo "export JAVA_HOME=/usr/local/jdk" >> /etc/profile
RUN echo "export PATH=${TOMCAT_HOME}/bin:${JAVA_HOME}/bin:$PATH" >> /etc/profile
RUN echo "export CLASSPATH=.:${JAVA_HOME}/lib/dt.jar:${JAVA_HOME}/lib/tools.jar" >> /etc/profile
# 生效环境变量
RUN source /etc/profile
# 暴露容器端口
EXPOSE 8080
# 启动tomcat
CMD ["/usr/local/tomcat/bin/catalina.sh","run"]

tomcatdir 目录最终会包含两个文件一个文件夹:

[root@localhost tomcatdir]# ls
Dockerfile  index.html  jdk

使用docker build命令构建镜像

docker build -t centos-tomcat:v1 .

输出:

[+] Building 29.9s (20/20) FINISHED                                                                                                                                                                 docker:default=> [internal] load build definition from Dockerfile                                                                                                                                                          0.0s=> => transferring dockerfile: 1.48kB                                                                                                                                                                        0.0s=> [internal] load metadata for docker.io/library/centos:centos7                                                                                                                                             1.5s=> [internal] load .dockerignore                                                                                                                                                                             0.0s=> => transferring context: 2B                                                                                                                                                                               0.0s=> CACHED [ 1/15] FROM docker.io/library/centos:centos7@sha256:be65f488b7764ad3638f236b7b515b3678369a5124c47b8d32916d6487418ea4                                                                              0.0s=> [internal] load build context                                                                                                                                                                             2.4s=> => transferring context: 283.27MB                                                                                                                                                                         2.4s=> [ 2/15] RUN curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo                                                                                                       0.8s=> [ 3/15] RUN yum -y install wget                                                                                                                                                                          18.7s=> [ 4/15] RUN wget https://dlcdn.apache.org/tomcat/tomcat-9/v9.0.97/bin/apache-tomcat-9.0.97.tar.gz                                                                                                         3.5s => [ 5/15] RUN tar xf apache-tomcat-9.0.97.tar.gz                                                                                                                                                            0.6s => [ 6/15] RUN mv apache-tomcat-9.0.97 /usr/local/tomcat                                                                                                                                                     0.8s => [ 7/15] RUN rm -rf apache-tomcat-9.0.97.tar.gz /usr/local/tomcat/webapps/*                                                                                                                                0.4s => [ 8/15] RUN mkdir /usr/local/tomcat/webapps/ROOT                                                                                                                                                          0.3s => [ 9/15] ADD ./index.html /usr/local/tomcat/webapps/ROOT/                                                                                                                                                  0.0s => [10/15] ADD ./jdk /usr/local/jdk                                                                                                                                                                          0.6s => [11/15] RUN echo "export TOMCAT_HOME=/usr/local/tomcat" >> /etc/profile                                                                                                                                   0.3s=> [12/15] RUN echo "export JAVA_HOME=/usr/local/jdk" >> /etc/profile                                                                                                                                        0.5s=> [13/15] RUN echo "export PATH=/usr/local/tomcat/bin:/usr/local/jdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" >> /etc/profile                                                      0.3s=> [14/15] RUN echo "export CLASSPATH=.:/usr/local/jdk/lib/dt.jar:/usr/local/jdk/lib/tools.jar" >> /etc/profile                                                                                              0.4s=> [15/15] RUN source /etc/profile                                                                                                                                                                           0.5s=> exporting to image                                                                                                                                                                                        0.7s=> => exporting layers                                                                                                                                                                                       0.6s=> => writing image sha256:c1e152369fa64e4bc2594d9d0f0e7b049b1e5ed776ceb0b8fa3273b63007b4f5                                                                                                                  0.0s=> => naming to docker.io/library/centos-tomcat:v1  

查看当前镜像

[root@localhost tomcatdir]# docker images
REPOSITORY                        TAG          IMAGE ID       CREATED          SIZE
centos-tomcat                     v1           c1e152369fa6   33 seconds ago   792MB

创建 Tomcat 容器

docker run -d -p 8080:8080 centos-tomcat:v1

测试:

[root@localhost tomcatdir]# curl http://localhost:8080
tomcat is running

8、使用Dockerfile生成容器镜像优化

1_减少镜像分层

Dockerfile 中包含多种指令,如果涉及到部署最多使用的算是 RUN 命令了,使用 RUN 命令时,不建议每次安装都使用一条单独的 RUN 命令,可以把能够合并安装指令合并为一条,这样就可以减少镜像分层。

FROM centos:centos7
LABEL maintainer="sy@163.com"
RUN curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
RUN yum -y update
RUN yum -y install gcc make wget
RUN wget http://download.redis.io/releases/redis-6.2.6.tar.gz
RUN tar xzf redis-6.2.6.tar.gz
WORKDIR /redis-6.2.6
RUN make -j 4
RUN make install
RUN mkdir -p /etc/redis
COPY redis.conf /etc/redis/
EXPOSE 6379
VOLUME ["/data"]
CMD ["redis-server", "/etc/redis/redis.conf"]

优化内容如下:

FROM centos:centos7
LABEL maintainer="sy@163.com"
RUN curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
RUN yum -y update && \yum -y install gcc make wget
RUN wget http://download.redis.io/releases/redis-6.2.6.tar.gz && \tar xzf redis-6.2.6.tar.gz && \cd redis-6.2.6 && \make -j 4 && \make install
RUN mkdir -p /etc/redis
COPY redis.conf /etc/redis/
EXPOSE 6379
VOLUME ["/data"]
CMD ["redis-server", "/etc/redis/redis.conf"]

2_清理无用数据

  • 一次RUN形成新的一层,如果没有在同一层删除,无论文件是否最后删除,都会带到下一层,所以要在每一层清理对应的残留数据,减小镜像大小。
  • 把生成容器镜像过程中部署的应用软件包做删除处理
FROM centos:centos7
LABEL maintainer="sy@163.com"
RUN curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
RUN yum -y update && \yum -y install gcc make wget && \yum clean all
RUN wget http://download.redis.io/releases/redis-6.2.6.tar.gz && \tar xzf redis-6.2.6.tar.gz && \cd redis-6.2.6 && \make -j 4 && \make install && \cd .. && \rm -rf redis-6.2.6.tar.gz redis-6.2.6
RUN mkdir -p /etc/redis
COPY redis.conf /etc/redis/
EXPOSE 6379
VOLUME ["/data"]
CMD ["redis-server", "/etc/redis/redis.conf"]

三次大小对比:

[root@localhost redisdir]# docker images
REPOSITORY                        TAG          IMAGE ID       CREATED         SIZE
centos-redis                      v3           bba7ae421d35   8 seconds ago   434MB
centos-redis                      v2           6f6f12c2b48a   2 minutes ago   801MB
centos-redis                      v1           4d6274008dbb   5 minutes ago   1.02GB

3_多阶段构建镜像

项目容器镜像有两种,一种直接把项目代码复制到容器镜像中,下次使用容器镜像时即可直接启动;另一种把需要对项目源码进行编译,再复制到容器镜像中使用。

不论是哪种方法都会让制作镜像复杂了些,并也会让容器镜像比较大,建议采用分阶段构建镜像的方法实现。

# 第一阶段:构建应用
FROM maven:3.8-jdk-11 AS build
ADD ./pom.xml pom.xml
ADD ./src src/
RUN mvn clean package# 第二阶段:运行时镜像
FROM tomcat:9
COPY --from=build target/*.war /usr/local/tomcat/webapps/ROOT.war

第一个 FROM 后边多了个 AS 关键字,可以给这个阶段起个名字

第二个 FROM 使用上面构建的 Tomcat 镜像,COPY 关键字增加了 --from 参数,用于拷贝某个阶段的文件到当前阶段。


4_构建出现问题

如果构建出现错误,可以使用如下命令清除相关缓存

docker builder prune # 删除没有任何标签或没有被引用的构建缓存文件
docker builder prune -a # 删除所有的构建缓存
docker system prune -f # 清理所有未使用的镜像、容器和构建缓存

相关文章:

Dockerfile容器镜像构建技术

文章目录 1、容器回顾1_容器与容器镜像之间的关系2_容器镜像分类3_容器镜像获取的方法 2、其他容器镜像获取方法演示1_在DockerHub直接下载2_把操作系统的文件系统打包为容器镜像3_把正在运行的容器打包为容器镜像 3、Dockerfile介绍4、Dockerfile指令1_FROM2_RUN3_CMD4_EXPOSE…...

LabVIEW实现MQTT通信

目录 1、MQTT通信原理 2、硬件环境部署 3、云端环境部署 4、程序架构 5、前面板设计 6、程序框图设计 7、测试验证 本专栏以LabVIEW为开发平台,讲解物联网通信组网原理与开发方法,覆盖RS232、TCP、MQTT、蓝牙、Wi-Fi、NB-IoT等协议。 结合实际案例,展示如何利用LabVIEW和常用…...

分布式事物XA、BASE、TCC、SAGA、AT

分布式事务——Seata 一、Seata的架构&#xff1a; 1、什么是Seata&#xff1a; 它是一款分布式事务解决方案。官网查看&#xff1a;Seata 2.执行过程 在分布式事务中&#xff0c;会有一个入口方法去调用各个微服务&#xff0c;每一个微服务都有一个分支事务&#xff0c;因…...

[创业之路-182]:《华为战略管理法-DSTE实战体系》-1-华为的发展历程和战略管理演变

目录 前言、华为在战略管理上做对了什么&#xff1f; 1、前瞻性的战略眼光 2、有效的战略解码 3、灵活的战略调整 4、注重创新和研发 5、以客户为中心的战略导向 6、完善的内部管理体系 一、华为不同时期的战略选择 1.1 华为不同时期的战略选择 1、创业初期&#xff…...

python爬虫--小白篇【爬取B站视频】

目录 一、任务分析 二、网页分析 三、任务实现 一、任务分析 将B站视频爬取并保存到本地&#xff0c;经过分析可知可以分为四个步骤&#xff0c;分别是&#xff1a; 爬取视频页的网页源代码&#xff1b;提取视频和音频的播放地址&#xff1b;下载并保存视频和音频&#x…...

web 自动化 selenium

1、下载Chrome对应的driver版本 我的chrome是 131.0.6778.109&#xff0c;我下载的driver是131.0.6778.69&#xff08;想找一模一样的&#xff0c;但是没有&#xff09; https://googlechromelabs.github.io/chrome-for-testing/ chromedriver下载 2、配置Chrome deriver及 …...

【OpenCV】Canny边缘检测

理论 Canny 边缘检测是一种流行的边缘检测算法。它是由 John F. Canny 在 1986 年提出。 这是一个多阶段算法&#xff0c;我们将介绍算法的每一个步骤。 降噪 由于边缘检测易受图像中的噪声影响&#xff0c;因此第一步是使用 5x5 高斯滤波器去除图像中的噪声。我们在前面的章…...

D94【python 接口自动化学习】- pytest进阶之fixture用法

day94 pytest的fixture详解 学习日期&#xff1a;20241210 学习目标&#xff1a;pytest基础用法 -- pytest的fixture详解 学习笔记&#xff1a; fixture的介绍 fixture是 pytest 用于将测试前后进行预备、清理工作的代码处理机制。 fixture相对于setup和teardown来说有以…...

关于idea-Java-servlet-Tomcat-Web开发中出现404NOT FOUND问题的解决

在做web项目时&#xff0c;第一次使用servlet开发链接前端和后端的操作&#xff0c;果不其然&#xff0c;遇到了诸多问题&#xff0c;而遇到最多的就是运行项目打开页面时出现404NOT FOUND的情况。因为这个问题我也是鼓捣了好久&#xff0c;上网查了许多资料才最终解决&#xf…...

SpringBoot Maven快速上手

文章目录 一、Maven 1.1 Maven 简介&#xff1a;1.2 Maven 的核心功能&#xff1a; 1.2.1 项目构建&#xff1a;1.2.2 依赖管理&#xff1a; 1.3 Maven 仓库&#xff1a; 1.3.1 本地仓库&#xff1a;1.3.2 中央仓库&#xff1a;1.3.3 私服&#xff1a; 二、第一个 SpringBoot…...

全面解析MySQL底层概念

mysql的概念 &#xff08;1&#xff09;mysql的架构 客户端请求--->连接器&#xff08;验证用户身份&#xff0c;给予权限&#xff09;--->查询缓存&#xff08;存在则直接返回&#xff0c;不存在则执行后续操作 --->分析器&#xff08;对SQL进行词法分析和语法分析…...

【C++】string类

一、C 标准库中的string类 1、string类 string类的文档介绍 首先string并不是STL中的&#xff0c;而是一个类string比STL出现的早 从上面可以看出string是从一个类模板中实例化出来的一个对象 在使用string类是必须要包头文件#include< string > 又因为是std中的类…...

《Python制作动态爱心粒子特效》

一、实现思路 粒子效果&#xff1a; – 使用Pygame模拟粒子运动&#xff0c;粒子会以爱心的轨迹分布并运动。爱心公式&#xff1a; 爱心的数学公式&#xff1a; x16sin 3 (t),y13cos(t)−5cos(2t)−2cos(3t)−cos(4t) 参数 t t 的范围决定爱心形状。 动态效果&#xff1a; 粒子…...

ssd202d-badblock-坏块检测

这边文章讲述的是坏快检测功能 思路: 1.第一次烧录固件会实现跳坏块,但是后续使用会导致坏块的产生; 于是我在uboot环境变量添加了两个变量来控制坏快 lb_badnum = //坏块个数 lb_badoff = //坏块所在位置 2.第一次开机会根据lb_badnum是否存在判断,如果不存在则保存上…...

使用html 和javascript 实现微信界面功能1

1.功能说明&#xff1a; 搜索模块: 提供一个搜索框&#xff0c;但目前没有实现具体的搜索功能。 好友模块: 在左侧的“好友”部分有一个“查看好友”按钮。点击左侧的“查看好友”按钮时&#xff0c;会在右侧显示所有好友的列表。列表中每个好友可以点击查看详情&#xff0c;包…...

趣味编程:猜拳小游戏

1.简介 这个系列的第一篇以猜拳小游戏开始&#xff0c;这是源于我们生活的灵感&#xff0c;在忙碌的时代中&#xff0c;我们每个人都在为自己的生活各自忙碌着&#xff0c;奔赴着自己所走向的那条路上&#xff0c;即使遍体鳞伤。 但是&#xff0c;生活虽然很苦&#xff0c;也不…...

图形化界面MySQL(MySQL)(超级详细)

目录 1.官网地址 1.1在Linux直接点击NO thanks..... 1.2任何远端登录&#xff0c;再把jj数据库给授权 1.3建立新用户 优点和好处 示例代码&#xff08;MySQL Workbench&#xff09; 示例代码&#xff08;phpMyAdmin&#xff09; 总结 图形化界面 MySQL 工具大全及其功…...

JavaScript技巧方法总结

技巧总结 字符串字符串首字母大写翻转字符串字符串过滤 数字十进制转换二进制、八进制、十六进制获取随机数字符串转数字指数幂运算 数组从数组中过滤出虚假值数组查找检测是否为一个安全数组数组清空实现并集、交集、和差集 对象检查对象是否为空从对象中选择指定数据动态属性…...

【Web】2023安洵杯第六届网络安全挑战赛 WP

目录 Whats my name easy_unserialize signal Swagger docs 赛题链接&#xff1a;GitHub - D0g3-Lab/i-SOON_CTF_2023: 2023 第六届安洵杯 题目环境/源码 Whats my name 第一段正则用于匹配以 include 结尾的字符串&#xff0c;并且在 include 之前&#xff0c;可以有任…...

【VUE2】纯前端播放海康视频录像回放,视频格式为rtsp格式,插件使用海康视频插件[1.5.4版本]

一、需求 1、后端从海康平台拉流视频回放数据&#xff0c;前端进行页面渲染播放&#xff0c;视频格式为rtsp eg&#xff1a; 基本格式&#xff1a;rtsp://<username>:<password><ip_addr>:<port>/<path>参数说明&#xff1a; username&#xff…...

mysql程序介绍,选项介绍(常用选项,指定选项的方式,特性),命令介绍(查看,部分命令),从sql文件执行sql语句的两种方法

目录 mysql程序 介绍 选项 介绍 常用选项 指定选项的方式 ​编辑配置文件 环境变量 选项特性 指定选项 选项名 选项值 命令 介绍 查看客户端命令 tee/notee prompt source system help contents 从.sql文件执行sql语句 介绍 方式 source 从外部直接导入…...

3D 生成重建032-Find3D去找到它身上的每一份碎片吧

3D 生成重建032-Find3D去找到它身上的每一份碎片吧 文章目录 0 论文工作1 论文方法2 实验结果 0 论文工作 该论文研究三维开放世界部件分割问题&#xff1a;基于任何文本查询分割任何物体中的任何部件。以往的方法在物体类别或部件词汇方面存在局限性。最近人工智能的进步在二…...

树莓派4B android 系统添加led灯 Hal 层

本文内容需要用到我上一篇文章做的驱动&#xff0c;可以先看文章https://blog.csdn.net/ange_li/article/details/136759249 一、Hal 层的实现 1.Hal 层的实现一般放在 vendor 目录下&#xff0c;我们在 vendor 目录下创建如下的目录 aosp/vendor/arpi/hardware/interfaces/…...

LLama系列模型简要概述

LLama-1&#xff08;7B, 13B, 33B, 65B参数量&#xff1b;1.4T tokens训练数据量&#xff09; 要做真正Open的AI Efficient&#xff1a;同等预算下&#xff0c;增大训练数据&#xff0c;比增大模型参数量&#xff0c;效果要更好 训练数据&#xff1a; 书、Wiki这种量少、质量高…...

Elasticsearch使用(2):docker安装es、基础操作、mapping映射

1 安装es 1.1 拉取镜像 docker pull swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/library/elasticsearch:7.17.3 1.2 运行容器 运行elasticsearch容器&#xff0c;挂载的目录给更高的权限&#xff0c;否则可能会因为目录权限问题导致启动失败&#xff1a; docker r…...

Python跳动的爱心

系列文章 序号直达链接表白系列1Python制作一个无法拒绝的表白界面2Python满屏飘字表白代码3Python无限弹窗满屏表白代码4Python李峋同款可写字版跳动的爱心5Python流星雨代码6Python漂浮爱心代码7Python爱心光波代码8Python普通的玫瑰花代码9Python炫酷的玫瑰花代码10Python多…...

安卓手机怎么轻松转换更新ip网络地址

随着移动互联网的快速发展&#xff0c;IP地址作为网络身份标识的重要性日益凸显。对于安卓手机用户来说&#xff0c;但有时候我们希望能够轻松转更换ip地址&#xff0c;以提高网络安全性或访问特定内容的需要。那么&#xff0c;安卓手机如何更换IP地址呢&#xff1f;本文将为您…...

socket UDP 环路回显的服务端

基于socket通讯的方式&#xff0c;无论用http或者udp或者自定义的协议&#xff0c;程序结构都是类似的。这个以UDP协议为例简要说明。 #include <stdio.h> // 标准输入输出库 #include <sys/types.h> // 提供了一些数据类型&#xff0c;如ssize_t #include <sy…...

单例模式的缺点

1. 违反单一职责原则 单例模式不仅管理对象的实例化&#xff0c;还负责提供对该实例的全局访问。这使得单例类承担了过多的职责。复杂的单例类可能变得难以维护和扩展。 2. 难以进行单元测试 单例模式引入了全局状态&#xff0c;使得测试环境中的依赖关系难以隔离。在测试中…...

如何通过看板进行跨境电商的圣诞商品数据分析与优化选品流程?

引言 随着圣诞季的临近&#xff0c;跨境电商迎来了重要的销售时机。选品工作对于跨境电商的成功至关重要&#xff0c;直接关系到销售业绩和利润。本文结合相关网页信息&#xff0c;深入探讨跨境电商在圣诞期间如何利用信息整合工具展开选品工作&#xff0c;并优化选品流程。同…...

【Linux】vi/vim 使用技巧

文章目录 1. 简介vi和vim的历史vi和vim的区别安装vimUbuntu/DebianCentOS/RHELFedoramacOSWindows 2. 基本操作启动和退出启动退出 模式介绍普通模式插入模式命令模式 光标移动基本移动高级移动 3. 文本编辑插入文本删除文本复制和粘贴撤销和重做 4. 搜索与替换基本搜索搜索文本…...

React的功能是什么?

以下是一些React的主要功能和特点&#xff1a; 组件化架构&#xff1a; React将UI拆分为可复用的独立组件&#xff0c;每个组件负责一部分UI的逻辑和展示。组件可以嵌套使用&#xff0c;形成复杂的UI结构。 虚拟DOM&#xff1a; React使用虚拟DOM来管理UI的状态和更新&#xff…...

【6】数据分析检测(DataFrame 1)

学习目标3 昨天&#xff0c;我们学习了Series。 而Pandas的另一种数据类型&#xff1a;DataFrame&#xff0c;在许多特性上和Series有相似之处。 今天&#xff0c;我们将学习DataFrame的相关知识&#xff1a; 1. DataFrame的概念 2. 构造一个DataFrame 3. DataFrame的常用…...

React初体验 - [Next.js项目]

效果 须知 Next.js与React有哪些区别?https://juejin.cn/post/7112334604027035655 React中文手册 https://react.docschina.org/learn/start-a-new-react-project Next.js中文手册 https://www.nextjs.cn/docs/getting-started 步骤 npx提速 - 更换npm国内源 - 参考文档 …...

学生信息管理系统(简化版)

前端部分&#xff08;vue2&#xff09; &#xff01;&#xff01;前端采用vue2框架&#xff0c;下面只写出必要的代码文件&#xff0c;想要使用需自行先创建vue项目 部分截图 下面是目录结构 下面是public文件夹里面的html文件 <!DOCTYPE html> <html lang"&q…...

网易云信荣获“HarmonyOS NEXT SDK星河奖”

近日&#xff0c;鸿蒙生态伙伴 SDK 开发者论坛在北京举行。 网易云信凭借在融合通信领域的技术创新和鸿蒙生态贡献&#xff0c;荣获鸿蒙生态“HarmonyOS NEXT SDK星河奖”。 会上&#xff0c;华为鸿蒙正式推出 SDK 生态繁荣伙伴支持计划&#xff0c;旨在为 SDK 领域伙伴和开发…...

Java版-图论-最小生成树-Prim算法

实现描述 如图: Prim算法的基本思想是从一个顶点开始,逐步构建最小生成树。具体步骤如下: 随机选取一个顶点作为起始点,并将其加入最小生成树的集合中。从该顶点出发,选择一条边连接到其他未被访问的顶点中的最小权值边。将该顶点加入到最小生成树的集合中,并标记为已…...

python-@property 和setter属性

T 一个装饰器&#xff0c;使得类中方法像属性一样被使用。 W 这是原本的类及其属性的访问 class Person():def __init__(self, firstname:str, lastname:str):self.first firstnameself.last lastnameself.full_name self.first self.lastdef printFullname(self):re…...

es有string类型字段吗

在较新的版本的 Elasticsearch (ES) 中,string 类型已经被移除,取而代之的是更具体的 text 和 keyword 类型。这一改变是在 Elasticsearch 5.0 版本引入的,目的是为了提供更好的性能和更明确的数据处理方式。 Text 类型 用途:text 类型用于全文搜索。当你有一个字段需要进…...

shell编程入门之提取字符并设置rtc时间

awk用法 awk是一款文本处理工具&#xff0c;通常在Unix和Linux操作系统中使用&#xff0c;用于以行为单位对文本进行处理和操作。它可以读取输入文本&#xff0c;对其进行处理&#xff0c;生成报表、统计信息等&#xff0c;并将结果输出到标准输出设备中。 它主要有以下特点&…...

数据库进阶教程:结合编程实现动态数据操作

在前一篇文章中&#xff0c;我们了解了数据库的基础知识及其核心操作。这次&#xff0c;我们将通过编程语言&#xff08;以 Python 为例&#xff09;与数据库进行交互&#xff0c;进一步提升你的数据库应用能力。我们将学习如何通过代码完成数据的插入、查询、更新和删除&#…...

高效可靠:吉客云数据集成到MySQL技术详解

测试-查询货品供应商报价-dange&#xff1a;吉客云数据集成到MySQL的技术案例分享 在现代企业的数据管理中&#xff0c;如何高效、可靠地实现不同系统之间的数据对接是一个关键问题。本文将聚焦于一个具体的系统对接集成案例——将吉客云的数据集成到MySQL数据库中&#xff0c…...

docker安装ddns-go(外网连接局域网)

docker先下载镜像&#xff0c;目前最新版是v6.7.6 也可以csdn资源下载 再导入dockers https://download.csdn.net/download/u014756339/90096748 docker load -i ddns-go.tar 启动 docker run -d --name ddns-go --restartalways --nethost -v /opt/ddns-go:/root jeessy/…...

hbuilder 安卓app手机调试中基座如何设置

app端使用基座 手机在线预览功能 1.点击运行 2.点击运行到手机或者模拟器 3.制作自定义调试基座 4.先生成证书【可以看我上一篇文档写的有】&#xff0c;点击打包 5.打包出android自定义调试基座【android_debug.apk】,【就跟app打包一样需要等个几分钟】 6.点击运行到手…...

【pyspark学习从入门到精通23】机器学习库_6

目录 分割连续变量 标准化连续变量 分类 分割连续变量 我们经常处理高度非线性的连续特征&#xff0c;而且只用一个系数很难拟合到我们的模型中。 在这种情况下&#xff0c;可能很难只通过一个系数来解释这样一个特征与目标之间的关系。有时&#xff0c;将值划分到离散的桶中…...

Postman高阶技能:Collection集合批量运行!

01、Collection&#xff08;集合&#xff09;介绍 当我们对一个或多个系统中的很多接口用例进行维护时&#xff0c;首先想到的就是对接口用例进行分类管理&#xff0c;同时还希望对这批接口用例做回归测试。 在 Postman 中也提供了这样一个功能&#xff0c;就是 Collection&a…...

ipset搭配iptables实现城市IP访问限制

最近刷了一台飞牛os&#xff0c;但是没有二次验证的功能&#xff0c;裸奔在公网上&#xff0c;看着让人揪心。于是最近研究了一下&#xff0c;设置防火墙只让某些城市能够访问设备&#xff0c;这样大大降低了服务器的风险&#xff0c;因为大多数被黑的原因都是来自国外。 1.下…...

WPF表格控件的列利用模块适配动态枚举类

将枚举列表转化到类内部赋值&#xff0c;在初始化表格行加载和双击事件时&#xff0c;触发类里面的枚举列表的赋值 <c1:Column Header"变更类型" Binding"{Binding ChangeType, ModeTwoWay, ValidatesOnExceptionsTrue, ValidatesOnDataErrorsTrue, NotifyOn…...

java引用相关(四大引用类型,软引用避免oom,弱引用表,虚引用和引用队列,可达性分析算法)

1. 什么是引用&#xff1f; 问题&#xff1a;什么是引用&#xff1f;Java中的引用是如何工作的&#xff1f; 答案&#xff1a; 引用 是对象的句柄&#xff0c;用于访问堆内存中的对象。在Java中&#xff0c;引用变量实际上存储的是对象的地址&#xff0c;而不是对象本身。通…...

图像识别 | Matlab基于卷积神经网络(CNN)的宝可梦识别源程序,GUI界面。附详细的运行说明。

图像识别 | Matlab基于卷积神经网络(CNN)的宝可梦识别源程序&#xff0c;GUI界面。附详细的运行说明。 目录 图像识别 | Matlab基于卷积神经网络(CNN)的宝可梦识别源程序&#xff0c;GUI界面。附详细的运行说明。预测效果基本介绍程序设计参考资料 预测效果 基本介绍 Matlab基…...