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

Docker 容器 - Dockerfile

Docker 容器 - Dockerfile

  • 一、Dockerfile 基本结构
  • 二、Dockerfile 指令详解
    • 2.1 FROM
    • 2.2 MAINTAINER
    • 2.3 COPY
    • 2.4 ADD
    • 2.5 WORKDIR
    • 2.6 VOLUME
    • 2.7 EXPOSE
    • 2.8 ENV
    • 2.9 RUN
    • 2.10 CMD
    • 2.11 ENTRYPOINT
  • 三、Dockerfile 创建镜像与模板
    • 3.1 Dockerfile 镜像
    • 3.2 镜像管理
    • 3.3 Dockerfile 模板
      • 3.3.1 Redhat 镜像模板
      • 3.3.2 JDK 镜像模板
      • 3.3.3 Tomcat 镜像模板
  • 四、Docker 数据持久化
  • 五、案例实战
    • 5.1 构建nginx服务镜像

DockerFile 是一个文本格式的配置文件,用户可以使用 DockerFile 来快速创建自定义的镜像

镜像的定制实际上就是 定制每一层所添加的配置、文件 。如果我们可以把每一层修改、安装、构建、操作的命令都写入一个脚本,用这个脚本来构建、定制镜像,那么之前提及的无法重复的问题、镜像构建透明性的问题、体积的问题就都会解决。这个脚本就是 Dockerfile

一、Dockerfile 基本结构

Dockerfile 分为四部分:基础镜像信息维护者信息镜像操作指令容器启动时执行指令

  • 每条指令创建一层:
    • FROM : 指明所基于的镜像名称
    • MAINTAINER:维护者信息,docker_user 维护(可以不写)。
    • COPY : 从 Docker 客户端的当前目录添加文件镜像操作 指令。
    • RUN : 构建镜像时 执行 make 命令,每运行一条 RUN 指令,镜像就添加新的一层,并提交(添加可写层)。
    • CMD : 指定在容器中运行什么命令,用来指定运行容器时的操作命令

Docker 镜像由只读层组成,每个只读层代表一个 Dockerfile 指令。这些层是堆叠的,每个层都是上一层的变化的增量

Docker 可以通过 读取 Dockerfile 指令 来自动构建镜像

# 在一个空目录下,新建一个名为 Dockerfile 文件
mkdir /www/	#/www这个目录是自己创建的,通过创建空目录,在此目录下创建文件
vim /www/Dockerfile# 编辑 Dockerfile
FROM nginx:1.27.4# 维护者,可以省略
MAINTAINER kendra kendra@docker.com# 启动容器
RUN mkdir /usr/share/nginx/html -p
RUN echo "hello docker" > /usr/share/nginx/html/index.html# 构建镜像 . : 根据当前上下文环境构建
docker build -t mynginx:v1.0 .# 运行
docker run --rm -it mynginx:v1.0 /bin/bash
[root@Docker-kd ]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
tomcat       11.0.5    e8c9a002d37b   7 weeks ago    467MB
nginx        1.27.4    4cad75abc83d   2 months ago   192MB
mysql        8.4.4     4a8a163431d3   3 months ago   769MB
busybox      latest    ff7a7936e930   7 months ago   4.28MB
[root@Docker-kd ]# ls /
afs  boot  etc   lib    media  opt   root  sbin  sys  usr
bin  dev   home  lib64  mnt    proc  run   srv   tmp  var
[root@Docker-kd ]# mkdir /www
[root@Docker-kd ]# cd /www/
[root@Docker-kd www]# ls
[root@Docker-kd www]# vim Dockerfile
[root@Docker-kd www]# cat Dockerfile
FROM nginx:1.27.4
MAINTAINER kendra kendra@docker.comRUN mkdir /usr/share/nginx/html -p
RUN echo "hello docker" > /usr/share/nginx/html/index.html

编辑界面:w保存,另一个会话即可构建镜像、运行,测试
在这里插入图片描述

  • 另起一个会话
    • 构建:docker build -t mynginx:v1.0 .
    • 运行:docker run --rm -it mynginx:v1.0 /bin/bash
[root@Docker-kd ~]# cd /www/
[root@Docker-kd www]# ls
Dockerfile
# 构建
[root@Docker-kd www]# docker build -t mynginx:v1.0 .
[+] Building 0.9s (7/7) FINISHED                                           docker:default=> [internal] load build definition from Dockerfile                                 0.0s=> => transferring dockerfile: 245B                                                 0.0s=> WARN: MaintainerDeprecated: Maintainer instruction is deprecated in favor of us  0.0s=> [internal] load metadata for docker.io/library/nginx:1.27.4                      0.0s=> [internal] load .dockerignore                                                    0.0s=> => transferring context: 2B                                                      0.0s=> [1/3] FROM docker.io/library/nginx:1.27.4                                        0.0s=> [2/3] RUN mkdir /usr/share/nginx/html -p                                         0.3s=> [3/3] RUN echo "hello docker" > /usr/share/nginx/html/index.html                 0.5s=> exporting to image                                                               0.0s=> => exporting layers                                                              0.0s=> => writing image sha256:7c6af446d495a180d79138a4abfc5c2b99d9b0f639a9e7e3c6bc8b8  0.0s=> => naming to docker.io/library/mynginx:v1.0                                      0.0s1 warning found (use docker --debug to expand):- MaintainerDeprecated: Maintainer instruction is deprecated in favor of using label (line 2)[root@Docker-kd www]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
mynginx      v1.0      7c6af446d495   3 minutes ago   192MB
tomcat       11.0.5    e8c9a002d37b   7 weeks ago     467MB
nginx        1.27.4    4cad75abc83d   2 months ago    192MB
mysql        8.4.4     4a8a163431d3   3 months ago    769MB
busybox      latest    ff7a7936e930   7 months ago    4.28MB
# 运行
[root@Docker-kd www]# docker run --rm -it mynginx:v1.0 /bin/bash
root@741204f40a3d:/# pwd
/
root@741204f40a3d:/# ls
bin   docker-entrypoint.d   home   media  proc	sbin  tmp
boot  docker-entrypoint.sh  lib    mnt	  root	srv   usr
dev   etc		    lib64  opt	  run	sys   var
root@741204f40a3d:/# cd /usr/share/nginx/html/
root@741204f40a3d:/usr/share/nginx/html# ls
50x.html  index.html
root@741204f40a3d:/usr/share/nginx/html# exit
exit

二、Dockerfile 指令详解

2.1 FROM

FROM 指令必须是 Dockerfile 中非注释行的第一个指令,即一个 Dockerfile 从FROM 语句开始,如果FROM语句没有指定镜像标签,则默认使用latest标签

FROM 指令用于为镜像文件构建过程指定基础镜像

FROM可以在一个 Dockerfile 中出现多次,如果有需求在一个 Dockerfile 中创建多个镜像。
如果FROM语句没有指定镜像标签,则默认使用latest标签

  • 命令格式如下:
FROM [--platform=<platform>] <image> [AS <name>]
或者
FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]
或者
FROM [--platform=<platform>] <image>[@<digest>] [AS <name>]FROM <image>[:<tag>]
FROM busybox:latest

2.2 MAINTAINER

指定维护者信,可以不写。

  • 命令格式如下:
MAINTAINER <authtor's detail>例如:
FROM busybox:latest
MAINTAINER "jock <jock@docker.com>"

2.3 COPY

用于从 docker 宿主机复制文件或者目录至创建的新镜像中的路径下,目标路径不存在时,会自动创建

  • 命令格式如下:
COPY <src>... <dest>
或
COPY ["<src>",... "<dest>"]

在这里插入图片描述

# COPY文件:
FROM busybox:latest
MAINTAINER "jock <jock@docker.com>"
COPY index.html /data/web/html/#构建:
# 在dockerfile同级目录下准备好index.html文件
[root@localhost ~]# vim index.html
<h1>Busybox httpd server</h1>
[root@localhost ~]# docker build -t busyboxhttpd:v0.1 ./#运行:
[root@localhost ~]# docker run --name web1 --rm busyboxhttpd:v0.1 cat /data/web/html/index.html
<h1>Busybox httpd server</h1>
# COPY 目录
vim index.html
<h1>Busybox httpd server</h1>
FROM busybox:latest
MAINTAINER "jock <jock@docker.com>"
COPY index.html /data/web/html/
COPY yum.repos.d /etc/yum.repos.d/

注:如果是复制目录,则其内部文件或子目录会被递归复制,但目录自身不会被复制;需要把复制目录名字也写在容器中要复制的路径下

#构建:
# 在dockerfile同级目录下准备好index.html文件
[root@localhost ~]# vim index.html
<h1>Busybox httpd server</h1>
[root@localhost ~]# docker build -t busyboxhttpd:v0.1 ./#运行:
[root@localhost ~]# docker run --name web1 --rm busyboxhttpd:v0.2 ls /etc/yum.repos.d/
along.repo
docker-ce.repo
epel-release-latest-7.noarch.rpm
epel-testing.repo
epel.repo

当使用本地目录为源目录时,推荐使用 COPY

2.4 ADD

ADD 指令类似于COPY指令,ADD支持使用TAR文件和URL路径,该命令将复制指定的路径下的内容到容器中的路径下

  • 命令格式如下:
ADD <src> .. <dest>
或
ADD ["<src>".. "<dest>"]

在这里插入图片描述

与COPY的区别
1、Dockerfile 中的 COPY 指令和 ADD 指令都可以将主机上的资源复制或加入到容器镜像中,都是在构建镜像的过程中完成的。
2、COPY 指令和 ADD 指令的区别在于是否支持从远程 URL 获取资源
COPY 指令只能从执行 docker build 所在的主机上读取资源并复制到镜像中
而 ADD 指令还支持通过 URL 从远程服务器读取资源并复制到镜像中
3、满足同等功能的情况下,推荐使用 COPY 指令。ADD 指令更擅长读取本地 tar 文件并解压缩
4、当要读取 URL 远程资源的时候,并不推荐使用 ADD 指令,而是建议使用 RUN 指令,在 RUN 指令中执行 wget 或 curl 命令。

  • COPY 网上路径(URL)的tar包
# COPY 网上路径(URL)的tar包
FROM busybox:latest
MAINTAINER "jock <jock@docker.com>"
COPY index.html /data/web/html/
COPY yum.repos.d /etc/yum.repos.d/
ADD http://nginx.org/download/nginx-1.15.8.tar.gz /usr/local/src/
#注:ADD 的 是网上的nginx下载路径#构建:
[root@localhost img1]# docker build -t busyboxhttpd:v0.3 ./#运行:
[root@localhost ~]# docker run --name web1 --rm busyboxhttpd:v0.3 ls
/usr/local/src
nginx-1.15.8.tar.gz
  • COPY 本地的路径的tar包
FROM busybox:latest
MAINTAINER "jock <jock@docker.com>"
COPY index.html /data/web/html/
COPY yum.repos.d /etc/yum.repos.d/
ADD nginx-1.15.8.tar.gz /usr/local/src/#构建:
# 在dockerfile同级目录下准备好yum.repos.d 目录
[root@localhost img1]# wget http://nginx.org/download/nginx-
1.15.8.tar.gz
[root@localhost img1]# docker build -t busyboxhttpd:v0.4 ./#运行:
[root@localhost ~]# docker run --name web1 --rm busyboxhttpd:v0.4 ls
/usr/local/src /usr/local/src/nginx-1.15.8
/usr/local/src:
nginx-1.15.8/usr/local/src/nginx-1.15.8:
CHANGES
CHANGES.ru
LICENSE
README
auto
conf
configure
contrib
html
man
src

2.5 WORKDIR

用于为 Dockerfile 中所有的 RUN、CMD、ENTRYPOINT、COPY 和 ADD 指定设定工作目录

  • 命令格式如下:
WORKDIR <dirpath>

在 Dockerfile 文件中,WORKDIR 指令可出现多次,其路径也可以为相对路径,不过,其是相对此前一个 WORKDIR 指令指定的路径。另外,WORKDIR 也可调用由ENV指定定义的变量

eg.
FROM busybox:latest
MAINTAINER "jock <jock@docker.com>"COPY index.html /data/web/html/
COPY yum.repos.d /etc/yum.repos.d/WORKDIR /usr/local/ADD nginx-1.15.8.tar.gz ./src/

2.6 VOLUME

用于在镜像中创建一个 挂载点 目录,以挂载 Docker host 上的卷或其它容器上的卷

  • 命令格式如下:
VOLUME <mountpoint>
或
VOLUME ["<mountpoint>"]

注:如果挂载点目录路径下此前在文件存在,docker run命令会在卷挂载完成后将此前的所有文件复制到新挂载的卷中

# eg.FROM busybox:latest
MAINTAINER "jock <jock@docker.com>"COPY index.html /data/web/html/
COPY yum.repos.d /etc/yum.repos.d/WORKDIR /usr/local/
ADD nginx-1.15.8.tar.gz ./src/VOLUME /data/mysql
# 构建:
[root@localhost ~]# docker build -t busyboxhttpd:v0.5 ./# 运行:[root@localhost ~]# docker run --name web1 --rm -it busyboxhttpd:v0.5
/bin/sh
/usr/local #
--- 另打开一个终端,查询存储卷
[root@localhost ~]# docker inspect -f {{.Mounts}} web1
[{volume
b788b8a50d69953e2b086b3b54ba683154647319a481246cb7ab2ff927b21372
/var/lib/docker/volumes/b788b8a50d69953e2b086b3b54ba683154647319a48124
6cb7ab2ff927b21372/_data /data/mysql local true }]

2.7 EXPOSE

用于为容器打开指定要监听的端口以实现与外部通信

  • 命令格式如下:
EXPOSE <port>[/ <protocol>] [<port>[/ <protocol>] ....

在这里插入图片描述

FROM busybox:latest
MAINTAINER "jock <jock@docker.com>"COPY index.html /data/web/html/
COPY yum.repos.d /etc/yum.repos.d/WORKDIR /usr/local/
ADD nginx-1.15.8.tar.gz ./src/VOLUME /data/mysqlEXPOSE 80/tcp

注:就算dockerfile 中有EXPOSE 指令暴露端口,但是不是真正的暴露;需要在启动容器时,使用 -p 选项真正的暴露端口

# 构建
[root@localhost img1]# docker build -t busyboxhttpd:v0.6 ./# 运行
[root@localhost ~]# docker run --name web1 -P --rm -it
busyboxhttpd:v0.6 /bin/httpd -f -h /data/web/html
--- 另打开一个终端,验证httpd 服务的80端口
[root@localhost ~]# docker inspect -f {{.NetworkSettings.IPAddress}}
web1 #查询容器的IP
172.17.0.2
[root@localhost ~]# curl 172.17.0.2:80
<h1>Busybox httpd server</h1>
--- 在宿主机通过暴露的端口访问httpd 服务
[root@localhost ~]# docker port web1
80/tcp -> 0.0.0.0:32768
[root@localhost ~]# curl 127.0.0.1:32768
<h1>Busybox httpd server</h1>

2.8 ENV

用于为镜像定义所需的环境变量,并可被 Dockerfile 文件中位于其后的其它指令(如 ENV、ADD、COPY 等)所调用,调用格式为$variable_ name 或 ${variable_ name}

  • 命令格式如下:
ENV <key> <value>
或
ENV <key>=<value> ...

在这里插入图片描述

FROM busybox:latest
MAINTAINER "jock <jock@docker.com>"ENV DOC_ROOT=/data/web/html/ \WEB_SERVER_PACKAGE="nginx-1.15.8"COPY index.html ${DOC_ROOT}
COPY yum.repos.d /etc/yum.repos.d/WORKDIR /usr/local/
ADD ${WEB_SERVER_PACKAGE}.tar.gz ./src/VOLUME /data/mysqlEXPOSE 8080:80/tcp
# 构建
[root@localhost ~]# docker build -t busyboxhttpd:v0.7 ./# 运行
[root@localhost ~]# docker run --name web1 -P --rm -it
busyboxhttpd:v0.7 ls /usr/local/src /data/web/html
/data/web/html:
index.html/usr/local/src:
nginx-1.15.8
--- 也可以使用printenv 查看变量验证
[root@localhost ~]# docker run --name web1 --rm -it busyboxhttpd:v0.7
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
DOC_ROOT=/data/web/html/
WEB_SERVER_PACKAGE=nginx-1.15.8
--- 在启动容器时,使用docker run -e 设置修改变量
[root@localhost ~]# docker run --name web1 -e
WEB_SERVER_PACKAGE=nginx-1.15.7 --rm -it busyboxhttpd:v0.7 printenv
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
WEB_SERVER_PACKAGE=nginx-1.15.7
DOC_ROOT=/data/web/html/

2.9 RUN

用于指定 docker build 过程中运行的程序,其可以是任何命令

  • 命令格式如下:
RUN <command>
或
RUN ["<executable>", "<param1>", "<param2>"]

在这里插入图片描述

FROM busybox:latest
MAINTAINER "jock <jock@docker.com>"ENV DOC_ROOT=/data/web/html/ \WEB_SERVER_PACKAGE="nginx-1.15.8.tar.gz"COPY index.html ${DOC_ROOT}
COPY yum.repos.d /etc/yum.repos.d/WORKDIR /usr/local/
ADD http://nginx.org/download/${WEB_SERVER_PACKAGE} ./src/VOLUME /data/mysqlEXPOSE 8080:80/tcpRUN cd ./src && \tar -xf ${WEB_SERVER_PACKAGE}
# 构建
[root@localhost ~]# docker build -t busyboxhttpd:v0.8 ./# 运行
[root@localhost ~]# docker run --name web1 -P --rm -it
busyboxhttpd:v0.7 ls /usr/local/src
nginx-1.15.8

2.10 CMD

类似于 RUN 指令,CMD 指令也可用于运行任何命令或应用程序

  • 不同点:

    • RUN 指令运行于映像文件构建过程中,而 CMD 指令运行于基于 Dockerfile 构建出的新映像文件启动一个容器时。
    • CMD 指令首要目的在于为启动的容器指定默认要运行的程序,且其运行结束后,容器也将终止。不过,CMD 指定的命令其可以被 docker run 的命令行选项所覆盖。
    • 在 Dockerfile 中可存在多个 CMD 指令,但仅最后一个会生效
  • 命令格式如下:

CMD <command>
或
CMD ["<executable>","<param1>","<param2>"]
或
CMD ["<param1>","<param2>"]

注:
前两种语法格式的意义同 RUN。
第三种则用于为 ENTRYPOINT 指令提供默认参数。
JSON 数组中,要使用双引号,单引号会出错。

FROM busybox
MAINTAINER "jock <jock@docker.com>"ENV WEB_DOC_ROOT="/data/web/html"RUN mkdir -p ${WEB_DOC_ROOT} && \echo "<h1>Busybox httpd server</h1>" > ${WEB_DOC_ROOT}/index.htmlCMD /bin/httpd -f -h ${WEB_DOC_ROOT}
# 构建
docker build -t busyboxhttpd:v1.1 ./# 运行
[root@localhost ~]# docker run --name web2 --rm -d busyboxhttpd:v1.1
20aa07198943887db51173e245392f75e3654525cb32242f2b04f0b3e007e47d
[root@localhost ~]# docker inspect -f {{.NetworkSettings.IPAddress}}
web2
172.17.0.2
[root@localhost ~]# curl 172.17.0.2
<h1>Busybox httpd server</h1>使用CMD定义的命令,在启动容器时,会被后面追加的指令覆盖;与下面ENTRYPOINT 指令对比
[root@localhost ~]# docker kill web2
web2
[root@localhost ~]# docker run --name web2 --rm busyboxhttpd:v1.1 ls /
bin
data
dev
etc
[root@localhost ~]# curl 172.17.0.2 被ls /覆盖,所以没有执行httpd服务

2.11 ENTRYPOINT

类似 CMD 指令的功能,用于为容器指定默认运行程序,从而使得容器像是一个单独的可执行程序。

与 CMD 不同的是,由 ENTRYPOINT 启动的程序不会被 docker run 命令行指定的参数所覆盖,而且,这些命令行参数会被当作参数传递给ENTRYPOINT 指定指定的程序。

不过,docker run 命令的 --entrypoint 选项的参数可覆盖 ENTRYPOINT 指令指定的程序

  • 命令格式如下:
ENTRYPOINT <command>
ENTRYPOINT ["<executable>", "<param1>", "<param2>"]

注:
docker run 命令传入的命令参数会覆盖 CMD 指令的内容并且附加到 ENTRYPOINT 命令最后做为其参数使用。
Dockerfile 文件中也可以存在多个 ENTRYPOINT 指令,但仅有最后一个会生效

FROM busybox
MAINTAINER "jock <jock@docker.com>"ENV WEB_DOC_ROOT="/data/web/html"RUN mkdir -p ${WEB_DOC_ROOT} && \echo "<h1>Busybox httpd server</h1>" > ${WEB_DOC_ROOT}/index.htmlENTRYPOINT /bin/httpd -f -h ${WEB_DOC_ROOT}
# 构建
[root@localhost ~]# docker build -t busyboxhttpd:v1.2 ./# 运行
[root@localhost ~]# docker run --name web2 --rm busyboxhttpd:v1.2 ls /
发现是不会执行ls / 这个命令;仍然执行的是ENTRYPOINT中设置的命令;与上面CMD 指令对比;
[root@localhost ~]# curl 172.17.0.2 #httpd服务仍然执行,没有被ls / 指令覆盖
<h1>Busybox httpd server</h1>

三、Dockerfile 创建镜像与模板

3.1 Dockerfile 镜像

编写完成 Dockerfile 之后,可以通过 docker build 命令来创建镜像

基本的格式为:

docker build [选项] 内容路径

该命令将读取指定路径下(包括子目录)的 Dockerfile,并将该路径下的所有内容发送给Docker服务端,由服务端来创建镜像

# 如果使用非内容路径下的Dockerfile,可以通过-f选项来指定其路径
docker build -t lagou/ubuntu:v1 .
#docker build 最后的 . 号,其实是在指定镜像构建过程中的上下文环境的目录

3.2 镜像管理

Docker 镜像由一系列层组成。每层代表镜像的 Dockerfile 中的一条指令。除最后一层外的每一层都是只读的

# 该 Dockerfile 包含四个命令,每个命令创建一个层
FROM ubuntu:18.04	#从 ubuntu:18.04 镜像创建只读层
COPY . /app		#从 Docker 客户端的当前目录添加一些文件
RUN make /app	#使用命令构建应用程序 make
CMD python /app/app.py	#最后一层指定在容器中运行什么命令

运行镜像并生成容器时,可以在基础层之上添加一个新的可写层(“容器层”)。对运行中的容器所做的所有更改(例如写入新文件,修改现有文件和删除文件)都将写入此可写容器层

容器和镜像之间的主要区别是可写顶层

在容器中添加新数据或修改现有数据的所有写操作都存储在此可写层中。删除容器后,可写层也会被删除。基础镜像保持不变。

因为每个容器都有其自己的可写容器层,并且所有更改都存储在该容器层中,所以多个容器可以共享对同一基础镜像的访问,但具有自己的数据状态

  • 查看镜像的分层信息
docker history 镜像ID
  • 要查看正在运行的容器的大致大小,可以使用以下 docker ps -s 命令
    • size :用于每个容器的可写层的数据量(在磁盘上)
    • virtual size :容器使用的只读图像数据加上容器的可写层使用的数据量size
      多个容器可以共享部分或全部只读图像数据。从同一图像开始的两个容器共享100%的只读数据,而具有不同图像的两个容器(具有相同的层)共享这些公共层
# 可以通过Docker仓库来传输我们的镜像,也可以通过文件模式
docker save 镜像ID -o xxxx.tar 或(docker save xxxx > xxxx.tar)docker load -i xxxx.tar 或docker (docker load < xxxx.tar)docker diff 容器IDdocker commit 容器ID openlab/testimage:version4 # 直接保存容器docker commit --change='CMD ["apachectl", "-DFOREGROUND"]' -c "EXPOSE 80" 容器ID openlab/testimage:version4 # 将正在运行的容器添加几个层之后再保存】

3.3 Dockerfile 模板

通过最小化Dockerfile中RUN 单独命令的数量来减少镜像中的层数。可以通过将多个命令合并为RUN 一行并使用Shell的机制将它们组合在一起来实现此目的

#在镜像中创建两层
RUN apt-get -y update
RUN apt-get install -y python#在镜像中创建一层
RUN apt-get -y update && apt-get install -y python

3.3.1 Redhat 镜像模板

dockerfile-redhat:

# 依据哪个镜像创建
From centos:7.6.1810# 指定容器内部使用语言
ENV LANG="en_US.UTF-8"
ENV LC_ALL="en_US.UTF-8"
# 使用亚洲/上海时区
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
# 创建工作目录
RUN mkdir -p /data/apps /data/data /data/logs ; ln -s /data/apps /apps
# 安装字体
RUN yum install -y epel-release
RUN yum groupinstall -y "fonts"
RUN yum install -y kde-l10n-Chinese
# 安装openssl等依赖包
RUN yum install -y openssl openssl-devel
RUN yum install -y crontabs cronolog ntp
# 安装数据库依赖
RUN yum install -y mariadb-libs
RUN ln -s /usr/lib64/mysql/libmysqlclient.so.18
/usr/lib64/libmysqlclient_r.so.16
RUN yum install -y gcc cmake
RUN yum install -y lrzsz telnet net-tools file bind-utils less
RUN yum install -y jq xml2; yum clean all
RUN yum install -y expat-devel apr-devel ghostscript ghostscript-devel
# 运行容器时的默认命令
CMD ["/bin/bash"]
  • 构建命令:
docker build -f dockerfile-redhat -t lagou/centos/7.6/centos .
docker run --rm -it lagou/centos/7.6/centos# 使用 Red Hat 9 作为基础镜像
FROM registry.access.redhat.com/ubi9/ubi:latest# 设置时区为亚洲/上海
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ >
/etc/timezone# 安装中文语言包
RUN dnf install -y kde-l10n-Chinese# 安装 openssl 和其他依赖包
RUN dnf install -y openssl openssl-devel# 安装 MySQL 8.4.4 的依赖
RUN dnf install -y \
libaio \
numactl-libs \
libtirpc \
libedit \
ncurses-compat-libs \
wget \
tar# 下载并安装 MySQL 8.4.4
RUN wget https://dev.mysql.com/get/Downloads/MySQL-8.4/mysql-8.4.4-
linux-glibc2.28-x86_64.tar.gz -O /tmp/mysql.tar.gz && \
tar -xzf /tmp/mysql.tar.gz -C /opt && \
mv /opt/mysql-8.4.4-linux-glibc2.28-x86_64 /opt/mysql && \
rm -f /tmp/mysql.tar.gz# 设置 MySQL 环境变量
ENV PATH=/opt/mysql/bin:$PATH# 创建 MySQL 数据目录
RUN mkdir -p /var/lib/mysql && \
chown -R mysql:mysql /var/lib/mysql# 初始化 MySQL
RUN mysqld --initialize-insecure --user=mysql --basedir=/opt/mysql --
datadir=/var/lib/mysql# 暴露 MySQL 默认端口
EXPOSE 3306# 设置容器启动时运行的命令
CMD ["mysqld", "--user=mysql"]
  • 构建和运行命令:
docker build -t redhat9-mysql8.4.4 .
docker run -d --name mysql-container -p 3306:3306 redhat9-mysql8.4.4

3.3.2 JDK 镜像模板

dockerfile-jdk:

# 使用 Red Hat 9 作为基础镜像
FROM registry.access.redhat.com/ubi9/ubi:latest# 设置时区为亚洲/上海
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ >
/etc/timezone# 安装必要的工具
RUN dnf install -y \
wget \
tar \
gzip \
&& dnf clean all# 下载并安装 JDK 21
# 注意:请根据实际需求替换 JDK 21 的下载链接
RUN wget
https://download.java.net/java/GA/jdk21/fd2272bbf8e04c3dbaee1377009041
6c/35/GPL/openjdk-21_linux-x64_bin.tar.gz -O /tmp/jdk21.tar.gz && \
tar -xzf /tmp/jdk21.tar.gz -C /opt && \
mv /opt/jdk-21 /opt/jdk && \
rm -f /tmp/jdk21.tar.gz# 设置 JDK 环境变量
ENV JAVA_HOME=/opt/jdk
ENV PATH=$JAVA_HOME/bin:$PATH# 验证安装
RUN java -version# 设置工作目录
WORKDIR /app# 默认启动命令(可以根据需要修改)
CMD ["java", "-version"]
  • 构建命令:
docker build -t redhat9-jdk21 .
docker run -it --rm redhat9-jdk21

3.3.3 Tomcat 镜像模板

dockerfile-jdk:

# 使用 Red Hat 9 作为基础镜像
FROM registry.access.redhat.com/ubi9/ubi:latest# 设置时区为亚洲/上海
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ >
/etc/timezone# 安装必要的工具
RUN dnf install -y \
wget \
tar \
gzip \
&& dnf clean all# 下载并安装 JDK 21
RUN wget
https://download.java.net/java/GA/jdk21/fd2272bbf8e04c3dbaee1377009041
6c/35/GPL/openjdk-21_linux-x64_bin.tar.gz -O /tmp/jdk21.tar.gz && \tar -xzf /tmp/jdk21.tar.gz -C /opt && \mv /opt/jdk-21 /opt/jdk && \rm -f /tmp/jdk21.tar.gz# 设置 JDK 环境变量
ENV JAVA_HOME=/opt/jdk
ENV PATH=$JAVA_HOME/bin:$PATH# 验证 JDK 安装
RUN java -version# 下载并安装 Tomcat 11.0.5
RUN wget https://archive.apache.org/dist/tomcat/tomcat-
11/v11.0.5/bin/apache-tomcat-11.0.5.tar.gz -O /tmp/tomcat.tar.gz && \tar -xzf /tmp/tomcat.tar.gz -C /opt && \mv /opt/apache-tomcat-11.0.5 /opt/tomcat && \rm -f /tmp/tomcat.tar.gz# 设置 Tomcat 环境变量
ENV CATALINA_HOME=/opt/tomcat
ENV PATH=$CATALINA_HOME/bin:$PATH# 创建 Tomcat 用户和组
RUN groupadd -r tomcat && \useradd -r -g tomcat -d $CATALINA_HOME -s /bin/false tomcat && \chown -R tomcat:tomcat $CATALINA_HOME# 暴露 Tomcat 默认端口
EXPOSE 8080# 设置工作目录
WORKDIR $CATALINA_HOME# 切换为 Tomcat 用户
USER tomcat# 启动 Tomcat
CMD ["catalina.sh", "run"]
  • 构建:
# 构建
docker build -t redhat9-tomcat11.0.5 .# 运行
docker run -d --name tomcat-container -p 8080:8080 redhat9-
tomcat11.0.5

访问:
打开浏览器,访问 http://localhost:8080 ,即可看到 Tomcat 的默认页面

  • 注意事项:
    • 如果需要部署自定义的 WAR 文件,可以将 WAR 文件复制到 /opt/tomcat/webapps 目录。
    • 如果需要持久化 Tomcat 的日志或配置文件,可以使用 Docker 卷( volumes )。
    • 如果需要调整 Tomcat 的配置,可以修改 /opt/tomcat/conf 目录下的配置文件。

四、Docker 数据持久化

  1. 创建一个卷,待后边使用
docker volume create test_volume
  1. 分别启动2个容器挂在上卷
# 在2个终端窗口启动2个容器
docker run -it --rm -v test_volume:/test nginx:1.27.4 /bin/bash
docker run -it --rm -v test_volume:/test nginx:1.27.4 /bin/bash
cd /test;
touch a.txt
ls /test# 在两个容器中我们均可以看到我们创建的文件,这样我们就可以做到了在多个容器之间实现数据共享

挂载在容器/test 目录内创建

Docker 不支持容器内安装点的相对路径。 多个容器可以在同一时间段内使用相同的卷。如果两个容器需要访问共享数据,这将很有用
注意:如果宿主机上的目录可以不存在,会在启动容器的时候创建

五、案例实战

5.1 构建nginx服务镜像

[root@docker ~]# ls
anaconda-ks.cfg  elasticsearch.yml  index3.html          redis:7.4.2.tar.gz
centos_7.tar.gz  index2.html        nginx.1.27.4.tag.gz
[root@docker ~]# docker load -i centos_7.tar.gz 
174f56854903: Loading layer  211.7MB/211.7MB
Loaded image: centos:7
[root@docker ~]# docker images
REPOSITORY      TAG       IMAGE ID       CREATED        SIZE
redis           latest    65750d044ac8   3 months ago   117MB
busybox         latest    ff7a7936e930   7 months ago   4.28MB
centos          7         eeb6ee3f44bd   3 years ago    204MB[root@docker ~]# mkdir demo
[root@docker ~]# cd demo/
[root@docker demo]# ls
[root@docker demo]# vim Dockerfile
[root@docker demo]# ls
Dockerfile
[root@docker demo]# cat Dockerfile 
FROM centos:7MAINTAINER jock 1062080730@qq.comRUN mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backupRUN curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo && \curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repoRUN yum install -y wget make gcc gcc-c++ pcre-devel zlib-devel openssl-devel && \yum clean allRUN wget https://nginx.org/download/nginx-1.24.0.tar.gz && \tar -zxf nginx-1.24.0.tar.gz && \rm nginx-1.24.0.tar.gzWORKDIR /nginx-1.24.0
RUN ./configure --prefix=/usr/local/nginx --with-http_ssl_module && \make && \make installRUN mkdir -p /usr/local/nginx/html && \echo "hello jock | welcome to nginx! | version 1.0" > /usr/local/nginx/html/index.htmlRUN echo '#!/bin/bash' > /start.sh && \echo 'hostname > /usr/local/nginx/html/hostname.html' >> /start.sh && \echo '/usr/local/nginx/sbin/nginx -g "daemon off;"' >> /start.sh && \chmod +x /start.shEXPOSE 80CMD ["/start.sh"]
[root@docker demo]# docker build -t myapp1.0 .
[+] Building 147.5s (13/13) FINISHED                                       docker:default=> [internal] load build definition from Dockerfile                                 0.0s=> => transferring dockerfile: 1.14kB                                               0.0s=> WARN: MaintainerDeprecated: Maintainer instruction is deprecated in favor of us  0.0s=> [internal] load metadata for docker.io/library/centos:7                          0.0s=> [internal] load .dockerignore                                                    0.0s=> => transferring context: 2B                                                      0.0s=> [1/9] FROM docker.io/library/centos:7                                            0.0s=> [2/9] RUN mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.rep  0.2s=> [3/9] RUN curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/r  0.4s=> [4/9] RUN yum install -y wget make gcc gcc-c++ pcre-devel zlib-devel openssl-  123.0s=> [5/9] RUN wget https://nginx.org/download/nginx-1.24.0.tar.gz &&     tar -zxf n  2.4s => [6/9] WORKDIR /nginx-1.24.0                                                      0.0s => [7/9] RUN ./configure --prefix=/usr/local/nginx --with-http_ssl_module &&       20.7s => [8/9] RUN mkdir -p /usr/local/nginx/html &&     echo "hello jock | welcome to n  0.1s => [9/9] RUN echo '#!/bin/bash' > /start.sh &&     echo 'hostname > /usr/local/ngi  0.1s => exporting to image                                                               0.5s => => exporting layers                                                              0.5s => => writing image sha256:9fc60c39bb353c478d9ddffd9599c5d5be1b3667a199a7b849aa0bf  0.0s => => naming to docker.io/library/myapp1.0                                          0.0s 1 warning found (use docker --debug to expand):- MaintainerDeprecated: Maintainer instruction is deprecated in favor of using label (line 3)[root@docker demo]# docker run --name myapp -d -p 80:80 myapp1.0:latest 
ded4100304c454ca8871f9db9384eb2736e6382cfad289e270262e43d85616e9
[root@docker demo]# docker ps
CONTAINER ID   IMAGE             COMMAND       CREATED          STATUS          PORTS                                 NAMES
ded4100304c4   myapp1.0:latest   "/start.sh"   11 seconds ago   Up 10 seconds   0.0.0.0:80->80/tcp, [::]:80->80/tcp   myapp
[root@docker demo]# curl localhost
hello jock | welcome to nginx! | version 1.0
[root@docker demo]# curl localhost/hostname.html
ded4100304c4
  • nginx
[root@docker demo]# rm -rf *
[root@docker demo]# vim Dockerfile
[root@docker demo]# cat Dockerfile
FROM centos:7MAINTAINER jock 1062080730@qq.comRUN mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backupRUN curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo && \curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repoRUN yum -y install epel-release && \yum -y install nginx && \yum clean allCOPY error.html /usr/share/nginx/html/error.htmlRUN echo 'server { error_page 404 /error.html; location = /error.html { root /usr/share/nginx/html; } }' > /etc/nginx/conf.d/default.confEXPOSE 80CMD ["nginx", "-g", "daemon off;"]
[root@docker demo]# vim error.html
[root@docker demo]# cat error.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>自定义错误页面</title><style>body {font-family: Arial, sans-serif;text-align: center;padding: 50px;}h1 {color: #333;}p {color: #666;}</style>
</head>
<body><h1>哎呀!页面未找到</h1><p>你所请求的页面可能已经被移除或者地址错误。</p>
</body>
</html>
[root@docker demo]# ls
Dockerfile  error.html
[root@docker demo]# docker build -t error:1.0 .
[+] Building 34.6s (11/11) FINISHED                                        docker:default=> [internal] load build definition from Dockerfile                                 0.0s=> => transferring dockerfile: 732B                                                 0.0s=> WARN: MaintainerDeprecated: Maintainer instruction is deprecated in favor of us  0.0s=> [internal] load metadata for docker.io/library/centos:7                          0.0s=> [internal] load .dockerignore                                                    0.0s=> => transferring context: 2B                                                      0.0s=> [1/6] FROM docker.io/library/centos:7                                            0.0s=> [internal] load build context                                                    0.0s=> => transferring context: 674B                                                    0.0s=> CACHED [2/6] RUN mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-B  0.0s=> CACHED [3/6] RUN curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyu  0.0s=> [4/6] RUN yum -y install epel-release &&     yum -y install nginx &&     yum c  34.3s=> [5/6] COPY error.html /usr/share/nginx/html/error.html                           0.0s=> [6/6] RUN echo 'server { error_page 404 /error.html; location = /error.html { r  0.2s=> exporting to image                                                               0.2s => => exporting layers                                                              0.2s => => writing image sha256:f658b54fa24cce7c0322ff844402e5917495b98650df3e43e78ff33  0.0s => => naming to docker.io/library/error:1.0                                         0.0s 1 warning found (use docker --debug to expand):- MaintainerDeprecated: Maintainer instruction is deprecated in favor of using label (line 3)[root@docker demo]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
error        1.0       f658b54fa24c   28 seconds ago   262MB
myapp        1.0       c48517613d32   7 minutes ago    210MB
myapp1.0     latest    9fc60c39bb35   15 minutes ago   368MB
kibana       8.17.3    7dcda0c152aa   7 weeks ago      1.18GB
mysql        8.4.4     4a8a163431d3   3 months ago     769MB
centos       7         eeb6ee3f44bd   3 years ago      204MB
[root@docker demo]# docker run --name error -d -p 80:80 error:1.0 
aeb56da0b8e066c9b135937f8e10ac934ba5e3fe3f87cd126b75e8a2e4409c04
[root@docker demo]# docker ps
CONTAINER ID   IMAGE       COMMAND                  CREATED         STATUS         PORTS                                 NAMES
aeb56da0b8e0   error:1.0   "nginx -g 'daemon of…"   4 seconds ago   Up 3 seconds   0.0.0.0:80->80/tcp, [::]:80->80/tcp   error
[root@docker demo]# curl localhost/error.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>自定义错误页面</title><style>body {font-family: Arial, sans-serif;text-align: center;padding: 50px;}h1 {color: #333;}p {color: #666;}</style>
</head>
<body><h1>哎呀!页面未找到</h1><p>你所请求的页面可能已经被移除或者地址错误。</p>
</body>
</html>
  • go
[root@docker demo]# vim main.go
[root@docker demo]# cat main.go 
package mainimport ("log""net/http"
)func main() {http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {w.Write([]byte("Hello, HTTPS!"))})log.Println("Server running on https://localhost:443")err := http.ListenAndServeTLS(":443", "server.crt", "server.key", nil)if err != nil {log.Fatal("ListenAndServeTLS: ", err)}
}[root@docker demo]# openssl req -x509 -nodes -days 365 -newkey rsa:2048 \-keyout server.key -out server.crt \-subj "/C=CN/ST=Demo/L=Demo/O=Demo/CN=localhost"
.............+++++++++++++++++++++++++++++++++++++++*..+...+..+............+.+........+....+..+++++++++++++++++++++++++++++++++++++++*.+.......+.....+......+....+..............+.+.........+...........+.+..+............+.+..+......+.......+...+.........+..+.+.....+....+...+........+...+.......+........+......+.+...............+.....+....+......+............+..+.........+....+.....................+............+..+.+..+....+........+............+.+.................+..........+..+.+.....+...+......+.............+......+......+...+...+..+......+....+..+.+.........+.....+.............+..+.+............+..+....+..+...+.........+.+..+....+.....+.............+......+......++++++
....+....+...+...........+....+...+..+++++++++++++++++++++++++++++++++++++++*.........+....+......+.................+...+.+...+......+..+++++++++++++++++++++++++++++++++++++++*.+.+.........+......+......+.........+.....+...+...+...+.+........+..........+..+.........+.........+.......+.....+..........+...+......+..+...+.+...+...+..+.+...........+.+........+......+................+............+..+.............+.....+...+...+.....................+..........+..................+...+..................+..+.......+..+....+.....................+...+...+..............+.+...............+..+......+.........+......+.+.....+......+...+....+..+...+...+............+.+......+......+...+...........+.+...+............+..+...+...+......+.+..+............+.+..............+....+..+....+..............+.+...+..........................++++++
-----[root@docker demo]# vim Dockerfile
[root@docker demo]# cat Dockerfile
FROM golang:alpineMAINTAINER jock 1062080730@qq.comWORKDIR /appCOPY main.go .RUN go build -o main main.goCOPY server.crt .
COPY server.key .EXPOSE 443CMD ["./main"]





相关文章:

Docker 容器 - Dockerfile

Docker 容器 - Dockerfile 一、Dockerfile 基本结构二、Dockerfile 指令详解2.1 FROM2.2 MAINTAINER2.3 COPY2.4 ADD2.5 WORKDIR2.6 VOLUME2.7 EXPOSE2.8 ENV2.9 RUN2.10 CMD2.11 ENTRYPOINT 三、Dockerfile 创建镜像与模板3.1 Dockerfile 镜像3.2 镜像管理3.3 Dockerfile 模板…...

C++ 中二级指针的正确释放方法

C 中二级指针的正确释放 一、什么是二级指针&#xff1f; 简单说&#xff0c;二级指针就是指向指针的指针。 即&#xff1a; int** p;它可以指向一个 int*&#xff0c;而 int* 又指向一个 int 类型的变量。 常见应用场景 动态二维数组&#xff08;例如 int** matrix&#x…...

解释器模式(Interpreter Pattern)

解释器模式&#xff08;Interpreter Pattern&#xff09; 是行为型设计模式之一&#xff0c;通常用于处理“语言”类问题&#xff0c;比如计算器、编程语言的解析等。它的核心思想是通过建立一个解释器&#xff0c;解析并解释由语法规则描述的语言&#xff0c;通常以**抽象语法…...

编译原理期末重点-个人总结——1 概论

概述 计算机语言的分类 低级语言&#xff1a;机器语言&#xff08;唯一能被计算机执行的&#xff09;&#xff0c;汇编语言 高级语言&#xff1a;JAVA &#xff0c;C 执行高级语言或汇编语言的步骤 高级语言程序或汇编语言程序> &#xff08;通过解释 或 翻译&#xff09;转…...

五一作业-day04

文章目录 1. **ps -ef是显示当前系统进程的命令,统计下当前系统一共有多少进程**2. **last命令用于显示所用用户最近1次登录情况,awk可以取出某一列,现在要取出last命令第1列并去重统计次数**3. **secure日志是用户的登录日志,过滤出secure日志中的Failed password的次数(用课堂…...

Java按字节长度截取字符串指南

在Java中&#xff0c;由于字符串可能包含多字节字符(如中文)&#xff0c;直接按字节长度截取可能会导致乱码或截取不准确的问题。以下是几种按字节长度截取字符串的方法&#xff1a; 方法一&#xff1a;使用String的getBytes方法 java public static String substringByBytes(…...

[特殊字符]Git 操作实战:如何将本地项目提交到远程 Gitee 仓库

在日常开发中&#xff0c;我们经常需要将本地开发的项目同步到远程代码仓库中&#xff08;如 GitHub、Gitee 等&#xff09;&#xff0c;以便团队协作或备份管理。本文将以 Gitee&#xff08;码云&#xff09; 为例&#xff0c;详细讲解如何将本地已有项目提交到远程仓库&#…...

【信息系统项目管理师-论文真题】2008上半年论文详解(包括解题思路和写作要点)

更多内容请见: 备考信息系统项目管理师-专栏介绍和目录 文章目录 试题1:企业级信息系统项目管理体系的建立1、写作要点2、解题思路项目管理流程和项目管理的工具试题2:项目的质量管理1、写作要点2、解题思路项目的早期阶段如何制定项目质量管理计划如何确保项目质量管理计划…...

C语言|函数的递归调用

函数的递归调用 (逐层分解&#xff0c;逐层合并) 自己调用自己&#xff0c;必须要知道什么时候停止调用&#xff0c;不然会造成电脑死机。 【知识点】 1 函数调用是通过栈实现的。 多个函数嵌套调用时&#xff0c;会按照先调用后返回的原则进行返回。 2 函数递归必须满足的两…...

QT 在圆的边界画出圆

QT 在圆的边界画出圆 QT 在圆的边界画出实心圆 在Qt中&#xff0c;要实现在圆的边界上绘制图形&#xff0c;你需要使用QPainter类来在QWidget或其子类的paintEvent中绘制。下面我将通过一个简单的例子来说明如何在Qt中绘制一个圆&#xff0c;并在其边界上绘制其他图形&#x…...

Guass数据库实验(数据字典设计、交叉表设计)

Assignment 2: Database Design 目录 Assignment 2: Database Design 数据库创建 新建用户bit&#xff0c;并创建数据库模式ass2 使用datastdui以该用户远程登陆 创建学科数据字典相关表 学科门类表 一级学科表 二级学科表 三级学科表 学科变更历史表 插入数据字典…...

算法题(139):牛可乐和魔法封印

审题&#xff1a; 本题需要我们将数组中包含在区间x~y之间的数据个数找到并输出 思路&#xff1a; 方法一&#xff1a;暴力解法 首先我们可以直接遍历一次数组&#xff0c;找到x的索引&#xff0c;然后再找到y的索引&#xff0c;并计算最终的元素个数&#xff0c;这里就要有O&a…...

LeetCode热题100--189.轮转数组--中等

1. 题目 给定一个整数数组 nums&#xff0c;将数组中的元素向右轮转 k 个位置&#xff0c;其中 k 是非负数。 示例 1: 输入: nums [1,2,3,4,5,6,7], k 3 输出: [5,6,7,1,2,3,4] 解释: 向右轮转 1 步: [7,1,2,3,4,5,6] 向右轮转 2 步: [6,7,1,2,3,4,5] 向右轮转 3 步: [5,6,…...

DeepSeek-Prover-V2:数学定理证明领域的新突破

前言 在人工智能飞速发展的当下&#xff0c;模型的迭代与创新层出不穷。 五一假期期间&#xff0c;DeepSeek 再次发力&#xff0c;推出了令人瞩目的新模型 ——DeepSeek-Prover-V2。 与大众期待的 R2 通用推理模型不同&#xff0c;这次 DeepSeek 将目光聚焦于数学定理证明领…...

调试——GDB、日志

调试——GDB、日志 1. gdb常用指令2. 如何生成core文件并调试&#xff1f;3. 如何调试正在运行的程序4. 调试多进程程序5. 调试多线程程序6. log日志 gcc编译器可以帮我们发现语法错误&#xff0c;但是对业务逻辑错误却无能为力。当我们想找出逻辑错误时&#xff0c;就需要调试…...

ARM子程序调用与返回

子程序&#xff08;也叫过程、函数、方法&#xff09;是一个能被调用和执行并返回到调用点那条指令的代码 段。 两个问题&#xff1a;如何将参数传递给子程序或从子程序中传递出来&#xff1f;怎么从子程序返回到调用点&#xff1f; 指令BSR Proc_A调用子程序Proc_A。 处理器将…...

WSL 安装 Debian 后,apt get 如何更改到国内镜像网址?

提问&#xff1a;Debian apt install 如何更改到国内镜像网址&#xff1f; 在 Debian 系统中&#xff0c;你可以通过修改 /etc/apt/sources.list 文件&#xff0c;将软件源更改为国内镜像网址&#xff0c;以加快软件包的下载速度。下面为你详细介绍操作步骤&#xff1a; 1. 备…...

SpringCloud GateWay网关

1、网关介绍 微服务网关&#xff08;Microservices Gateway&#xff09;是微服务架构中的核心组件&#xff0c;充当所有客户端请求的统一入口&#xff0c;负责请求的路由、过滤和聚合等操作。它是微服务与外部系统&#xff08;如Web、移动端&#xff09;之间的中间层&#xff0…...

可视化大屏开发全攻略:技术与实践指南

引言 在数字化浪潮席卷全球的当下&#xff0c;数据已成为企业乃至整个社会发展的核心驱动力。从繁华都市的交通管控中心&#xff0c;到大型企业的数据运营中枢&#xff0c;可视化大屏无处不在&#xff0c;以直观、震撼的方式展示着数据的魅力与价值。它就像是一扇通往数据世界…...

如何设计一个为QStackWidget的界面切换动画?

目录 前言 接口考虑 实现的思路 前言 笔者这段时间沉迷于给我的下位机I.MX6ULL做桌面&#xff0c;这里抽空更新一下QT的东西。这篇文章是跟随CCMoveWidget一样的文章&#xff0c;尝试分享自己如何书写这份代码的思考的过程 接口考虑 笔者不太想使用继承的方式重新写我们的…...

LeetCode 0790.多米诺和托米诺平铺:难想条件的简单动态规划

【LetMeFly】790.多米诺和托米诺平铺&#xff1a;难想条件的简单动态规划 力扣题目链接&#xff1a;https://leetcode.cn/problems/domino-and-tromino-tiling/ 有两种形状的瓷砖&#xff1a;一种是 2 x 1 的多米诺形&#xff0c;另一种是形如 "L" 的托米诺形。两种…...

模拟芯片设计中数字信号处理一些常用概念(一)

模拟芯片设计中经常用时域场景思考来解决问题,但实际上很多地方如果采用频域角度思考,解决问题更快更方便。 时域和频域的对照关系如下: a、如果时域信号是周期的,那么它的频谱就是离散的。 b、如果时域信号是非周期的,那么它的频谱就是连续的。 c、如果时域信号是离散的…...

c++进阶——AVL树主要功能的模拟实现(附带旋转操作讲解)

文章目录 AVL树的实现AVL树的概念及引入AVL树调整问题AVL树的实现AVL树的结构AVL树的插入插入的流程更新平衡因子的原则实现插入的基本框架(插入 调整平衡因子)旋转操作右单旋左单旋左右双旋右左双旋 合并旋转代码 测试部分平衡检测接口测试用例 对于其他接口的说明 AVL树的实…...

一个电商场景串联23种设计模式:创建型、结构型和行为型

理解了&#xff01;你希望有一个具体的项目案例&#xff0c;能够涵盖所有23种设计模式&#xff0c;并且将它们分类为创建型、结构型和行为型。这个需求非常好&#xff0c;能够帮助你从实际的应用场景理解每种设计模式的用法。 为了实现这个目标&#xff0c;我将为你设计一个电…...

浅拷贝和深拷贝的区别

Person p1 new Person(10);Person p2 p1;p2.age 20;System.out.println(p1p2); // trueSystem.out.println(p1.age); // 20 这种做法只是复制了对象的地址&#xff0c;即两个变量现在是指向了同一个对象&#xff0c;任意一个变量&#xff0c;操作了对象的属性&#xff0c;都…...

Java开发者面试实录:微服务架构与Spring Cloud的应用

面试场景 面试官: 请介绍一下你的基本情况。 程序员: 大家好&#xff0c;我叫张小明&#xff0c;今年27岁&#xff0c;硕士学历&#xff0c;拥有5年的Java后端开发经验。主要负责基于Spring Boot开发企业级应用&#xff0c;以及微服务架构的设计和实现。 面试官: 好的&#…...

在Ubuntu系统中安装桌面环境

在 Ubuntu 系统中安装桌面环境可以通过包管理器 apt 或工具 tasksel 实现。以下是详细的安装方法和常见桌面环境的选择&#xff1a; --- ### **1. 准备系统更新** 在安装前&#xff0c;建议更新软件源和系统包&#xff1a; bash sudo apt update && sudo apt upgrade…...

多语言笔记系列:Polyglot Notebooks 中使用 xUnit 单元测试

Polyglot Notebooks 中使用 xUnit 单元测试 本文目录 Polyglot Notebooks 中使用 xUnit 单元测试[TOC](本文目录)Polgylot Notebooks 并没有直接支持单元测试框架。不能像VS里那样方便的进行单元测试。简单远行的话&#xff0c;可以使用下面的方案&#xff01;1、引入必要的NuG…...

Cisco Packet Tracer 选项卡的使用

目录 设备Config选项卡的使用 Realtime and Simulation模式&#xff08;数据包跟踪与分析&#xff09; 设备Desktop选项卡的使用 设备Config选项卡的使用 Hostname NVRAM Startup Config----Load 加载 INTERFACE 点击on Save 如果&#xff0c;不把Running Config保存为Sta…...

杨校老师竞赛课之C++备战蓝桥杯初级组省赛

目录 1. 灯塔 题目描述 输入描述 输出描述 输入样例1 输出样例1 输入样例2 输出样例2 数据说明 2. 子区间 题目描述 输入描述 输出描述 输入样例 输出样例 数据说明 3. 染色 题目描述 输入描述 输出描述 输入样例1 输出样例1 输入样例2 输出样例2 数据…...

gcc/g++用法摘记

链接静态库 gcc main.o -L/path/to/libs -lmylib -o myprogram 【待续】...

kotlin 扩展函数

Kotlin 扩展函数的定义与使用 定义扩展函数 Kotlin 的扩展函数是一种强大的机制&#xff0c;允许开发者为已有的类添加额外的功能&#xff0c;而无需继承该类或对其进行任何修改。这种特性极大地提高了代码的灵活性和可读性。 扩展函数可以通过在函数名称前指定目标类型的接…...

机器人强化学习入门学习笔记

(1)物理引擎 物理引擎就是模拟真实世界物理规律的软件工具。它会根据你给定的物体、质量、形状、力等信息,计算这些物体在时间上的运动和相互作用。如果你设计了一个机器人,那物理引擎就是“虚拟现实世界”,让机器人在里面“活起来”,模拟它走路、抓东西、摔倒等动作。而…...

《RESTful API版本控制的哲学思辨:稳定性与创新性的终极平衡》

有效的版本控制&#xff0c;就如同精密仪器中的校准装置&#xff0c;确保API在不断升级的过程中&#xff0c;依然能与旧有系统无缝对接&#xff0c;维持整个生态的平稳运行。 不同的客户端对API的依赖程度和使用方式各不相同。有些客户端可能因为各种原因&#xff0c;无法及时…...

spring中spring-boot-configuration-processor的使用

spring-boot-configuration-processor 是 Spring Boot 提供的注解处理器&#xff0c;用于在编译阶段生成配置元数据文件&#xff08;spring-configuration-metadata.json&#xff09;&#xff0c;从而优化开发体验。以下是其核心功能和使用指南&#xff1a; 一、核心功能 IDE 智…...

30天开发操作系统 第27天 -- LDT与库

前言 大家早上好&#xff0c;我们今天的第一个任务就是修复昨天晚上的那个bug。是个什么bug来着&#xff1f;就是用nsct命令运行的应用程序&#xff0c;无论是按ShiftF1还是点击窗口的“x”按钮都没有反应的那个bug啦。 我们得先来找到出问题的原因&#xff0c;然后才能采取对…...

std::move()详解

一、std::move()的作用和原理 本质&#xff1a; std::move()并不像字面意思“搬走”那些对象&#xff0c;而是&#xff1a; 将传入的对象“强制转化”为右值引用类型&#xff0c;从而开启“移动语义”。 在源码层面&#xff1a; 复制代码 template<typename T> std::…...

linux系统基本操作命令

文件和目录操作 ls&#xff1a;列出目录内容。 例如&#xff1a;ls -l 显示详细信息&#xff0c;ls -a 显示包括隐藏文件在内的所有文件。 cd&#xff1a;改变当前目录。 例如&#xff1a;cd /home/username 切换到指定目录。 pwd&#xff1a;显示当前目录的完整路径。 mk…...

python打卡day16

NumPy 数组基础 因为前天说了shap&#xff0c;这里涉及到数据形状尺寸问题&#xff0c;所以需要在这一节说清楚&#xff0c;后续的神经网络我们将要和他天天打交道。 知识点&#xff1a; numpy数组的创建&#xff1a;简单创建、随机创建、遍历、运算numpy数组的索引&#xff1a…...

架构进阶:什么是数据架构,如何理解数据架构?(华为)

数据架构是企业架构的重要组成部分,DAMA、IBM 及国内大厂对其定义各有侧重。它包含数据资产目录、数据标准、数据模型和数据分布四个组件。数据资产目录可梳理企业数据资产,数据标准统一数据含义和规则,数据模型反映业务对象关联关系,数据分布呈现数据流动情况。数据架构是…...

基于EFISH-SCB-RK3576工控机/SAIL-RK3576核心板的KTV点歌主机技术方案‌(国产化替代J1900的全场景技术解析)

‌一、硬件架构设计‌ ‌多媒体处理模块‌ ‌超高清解码‌&#xff1a; RK3576 NPUGPU协同解码&#xff0c;支持4K60fps H.265硬解&#xff08;功耗<5W&#xff09;&#xff0c;支持8路1080P视频同步预览对比J1900需外接VPU解码芯片&#xff0c;硬件成本降低40%&#xff0c;…...

Java面试深度解密:Spring Boot、Redis、日志优化、JUnit5及Kafka事务核心技术解析

模拟面试实战 面试官&#xff1a;请解释Spring Boot的自动配置原理&#xff1f;哪些关键注解参与了这一过程&#xff1f; xbhog&#xff1a;Spring Boot通过AutoConfiguration标记核心配置类&#xff0c;通过ConditonalOnClass和ConditionalOnMissingBean判断依赖是否存在并自…...

内存碎片深度剖析

目录 什么是内存碎片 内部碎片的解决 malloc STL二级空间配置器 外部碎片的解决 伙伴系统算法 slab分配器 什么是内存碎片 内存碎片是指在内存中存在的一些不连续的、较小的空闲内存块&#xff0c;这些小块内存由于太小而无法被有效地分配给程序使用&#xff0c;从而导…...

飞帆网页中使用 i 评论插件

https://fvi.cn/786...

DeepSeek成本控制的三重奏

知识蒸馏 使用规则引擎筛选合成数据&#xff0c;来替代90%的人工标注 动态精度切换&#xff1a;“节能模式” 根据任务复杂度自动切换FP16/INT8精度&#xff0c;单位token能耗低至0.0028瓦时&#xff0c;推理电费成本降低82% 极致压缩训练 通过以上的技术&#xff0c;降低训练…...

五一の自言自语 2025/5/5

今天开学了&#xff0c;感觉还没玩够。 假期做了很多事&#xff0c;弄了好几天的路由器、监控、录像机&#xff0c;然后不停的出现问题&#xff0c;然后问ai&#xff0c;然后解决问题。这次假期的实践&#xff0c;更像是计算机网络的实验&#xff0c;把那些交换机&#xff0c;…...

效整理文件信息!一键生成文件夹目录的工具

一、软件介绍 大家好&#xff0c;今天给大家推荐一款实用的文件夹目录生成工具&#xff0c;它能快速提取文件夹内的文件信息&#xff0c;并整理成Excel表格&#xff0c;包含文件名、路径、类型、创建/修改时间、大小等关键数据。 为什么需要这个工具&#xff1f; 之前我想整理…...

关闭ollama开机自启动

不同操作系统关闭Ollama开机自启动的方法有所不同&#xff0c;以下是常见操作系统的具体方法&#xff1a; Windows系统 通过任务管理器&#xff1a;按Ctrl Shift Esc打开任务管理器&#xff0c;切换到“启动”选项卡&#xff0c;在列表中找到Ollama&#xff08;或相关条目&a…...

2025 年最新树莓派 Pico 连接 ESP8266 模块实现 WiFi 通信、搭建 TCP 服务器实现数据交互详细教程

AT 指令基本结构概述 AT 指令最初由 Hayes 公司为其调制解调器&#xff08;modem&#xff09;开发&#xff0c;目的是提供一种标准化的方式来控制通信设备。最早的 Hayes Smartmodem 300 调制解调器&#xff08;1981年&#xff09;引入了这一指令集&#xff0c;因此 AT 指令也…...

java类=null的回收

在Java&#xff08;或类似使用垃圾回收的语言&#xff09;中&#xff0c;当你执行 a null 后&#xff0c;对象 B() 是否会被回收取决于是否还有其他引用指向它。具体分析如下&#xff1a; 关键点&#xff1a; 引用链分析&#xff1a; 初始时&#xff1a;a 引用了 A 实例&#…...