最新版本更新
https://code.jiangjiesheng.cn/article/341
1.linux环境制作jdk17的docker镜像
1.1 jdk17官方下载【长期支持版本】
jdk-17下载:
https://download.oracle.com/java/17/latest/jdk-17_linux-x64_bin.tar.gz
【实际压缩包中的文件夹名称:jdk-17.0.11】
1.2 在线教程
docker制作高版本jdk17镜像踩坑
https://blog.csdn.net/qq_44624290/article/details/139303741
详解 docker 镜像制作的两种方式( 含有 在容器中安装软件制作新镜像)
https://blog.csdn.net/sinat_41883985/article/details/135295923
CentOS Docker 安装(通过yum安转)
https://www.runoob.com/docker/centos-docker-install.html
使用docker构建jdk17镜像(包括添加镜像源)
https://blog.csdn.net/m0_58608667/article/details/139680578
1.3 具体步骤
mkdir -p /j-deploy/packages/docker/
cd /j-deploy/packages/docker/
wget https://download.oracle.com/java/17/latest/jdk-17_linux-x64_bin.tar.gz
sudo yum install -y yum-utils
sudo yum-config-manager \
--add-repo \
https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
安装Docker Engine:
sudo yum install docker-ce docker-ce-cli containerd.io docker-compose-plugin
sudo systemctl start docker
sudo docker run hello-world
docker ps -a
docker exec -it hello-world bash (运行失败)
编写Dockerfile文件
Dockerfile相关的命令:
CMD ["mkdir", "-p", "/ecp-collector"]
vi Dockerfile
FROM centos:7
MAINTAINER emon
WORKDIR /usr/local/java
ADD jdk-17_linux-x64_bin.tar.gz /usr/local/java/
ENV JAVA_HOME=/usr/local/java/jdk-17.0.11
ENV CLASSPATH=.:$JAVA_HOME/lib/jrt-fs.jar
ENV PATH=$PATH:$JAVA_HOME/bin
构建docker镜像
docker build -t='jdk17_js' .
注意:构建过程中报错,找不到centos 7 之类的
vim /etc/docker/daemon.json (没有的话,就是新建)
{
"registry-mirrors": [
"https://l10nt4hq.mirror.aliyuncs.com",
"http://hub-mirror.c.163.com",
"http://mirrors.ustc.edu.cn/",
"http://mirror.azure.cn/"
]
}
重启docker
systemctl restart docker
docker info | grep -i "mirror"
再次构建docker镜像
docker build -t='jdk17_js' .
构建完成后查看镜像
docker images
运行镜像
【run是执行 创建 容器,所以实际不能重复执行,需要先rm移除】
docker run -di --name jdk17_js jdk17_j
AI解读
这个修改后的命令 docker run -di --name jdk17_js jdk17_js 用来启动一个新的Docker容器,并进行了以下操作:
docker run: 命令用于创建一个新的容器并运行一个命令。
-d: 这个选项让容器在后台运行,也就是守护进程模式。当你不想让容器的输出占据你的终端,或者你需要容器一直运行而不在当前会话中中断时,会用到这个选项。
-i: 表示以交互模式运行容器。它保持标准输入(STDIN)打开,使得容器进程可以接收输入数据。通常与 -t 一起使用来分配一个伪终端,但这里没有 -t,意味着虽然容器可以接收输入,但它不会直接附加到一个终端上进行交互。
--name jdk17_js: 指定新创建的容器的名称为 jdk17_js。给容器命名对于之后管理和识别容器特别有帮助,比如当你需要停止、启动或删除这个容器时可以直接通过名字操作。
jdk17_js: 最后一部分再次提到的 jdk17_js 是指定了要使用的镜像名称。Docker将查找本地是否存在这个名字的镜像;如果不存在,Docker会尝试从默认的镜像仓库(通常是Docker Hub)中拉取。这个镜像应该是基于Java Development Kit (JDK) 17定制或包含的,适合运行Java应用程序。
总结来说,这个命令的目的是:使用名为 jdk17_js 的Docker镜像,以后台且交互模式启动一个新的容器,并将此容器命名为 jdk17_js。这通常是在准备执行或部署需要Java 17环境的应用程序时使用的步骤。由于没有明确指定容器启动后执行的命令,默认会执行该镜像中的 ENTRYPOINT 或者 /bin/bash(如果镜像中没有明确设置 CMD 或 ENTRYPOINT)。
进入jdk17_js容器
docker exec -it jdk17_js bash
java -version
java version "17.0.11" 2024-04-16 LTS
Java(TM) SE Runtime Environment (build 17.0.11+7-LTS-207)
Java HotSpot(TM) 64-Bit Server VM (build 17.0.11+7-LTS-207, mixed mode, sharing)
关闭jdk17_js容器
docker stop jdk17_js
重启jdk17_js容器
docker restart jdk17_js
docker start jdk17_js
1.4 修改镜像名称(重新标记(Tag))【之前创建的名称是java17_js】
docker tag java17_js jdk17_js:latest
docker push jdk17_js:latest 【推送到仓库,可选】
docker rmi java17_js:latest 【如果需要删除】
docker images 【查看修改后的镜像列表】
docker stop java17_js【关闭java17_js】
docker run -di --name jdk17_js jdk17_js
1.5 清除|删除已经Exited的容器
docker ps -aq -f status=exited 【查看已经Exited的容器id】
docker ps -a | grep 'Exited' 【查看已经Exited的容器id】
docker ps -a | grep 'Exited' | awk '{print $12}' 【查看已经Exited的容器名称】
docker rm $(docker ps -aq -f status=exited) 【指定删除所有已经Exited的容器】
补充 docker rm 默认清除|删除的是已停止的容器,如果要清除正在运行中或多个容器
docker rm -f [name1] [name2] ...
docker container prune 【一键删除所有已经Exited的容器】
1.6 清除|删除镜像
docker images
docker rmi <镜像ID或镜像名:标签>
docker rmi ubuntu:latest
docker rmi -f <镜像ID或镜像名:标签> 【 参数强制删除,但这会导致依赖于该镜像的所有容器也被删除】
docker image prune -a 【一键删除所有未被任何容器使用的镜像】
1.7 基于已有的jdk容器,制作一个后端代码服务容器
1.7.1 方式1 通过Dockerfile
创建 Dockerfile
# 使用现有的 JDK 17 镜像作为基础镜像
FROM jdk17_js
# 设置工作目录
WORKDIR /app
# 将后端应用的 JAR 文件复制到容器中的工作目录
COPY your-backend-service.jar /app/your-backend-service.jar
# 设置容器启动时执行的命令,这里假设是一个 Spring Boot 应用
CMD ["java", "-jar", "your-backend-service.jar"]
# 如果你的应用需要特定的端口,可以暴露出来
EXPOSE 8080
开始构建镜像
docker build -t your-backend-image-name .
这里的 your-backend-image-name 是你给新镜像自定义的名称,. 表示 Dockerfile 所在的当前目录。
运行新的 Docker 容器
docker run -p 8080:8080 -d your-backend-image-name
这个命令将容器内的 8080 端口映射到主机的 8080 端口,并以后台模式运行容器。
1.7.2 通过docker commit
docker commit命令可以基于一个正在运行的容器创建一个新的镜像,这样你可以在已有 JDK 容器的基础上,安装额外的软件、添加代码、修改配置等,然后提交这些更改作为一个新的镜像。下面是使用 docker commit 来实现基于已有 JDK 容器创建后端代码服务容器的大致步骤:
第一步:启动基础 JDK 容器并安装/配置
启动基础容器:首先,启动你的 JDK 容器,进入交互式模式以便安装额外的依赖或复制文件。
docker run -it --name base_jdk_container jdk17_js /bin/bash
在容器中安装依赖、复制代码:在容器内部,你可以执行任何必要的操作,比如安装额外的软件包、复制你的后端代码、设置环境变量等。例如,如果需要,你可以用 apt-get(如果是基于Debian的镜像)安装额外的工具,或者直接复制你的应用到容器内。
第二步:提交容器为新镜像
完成所有必要的配置和文件添加后,退出容器(使用 exit 命令),然后使用 docker commit 命令来保存你的改动为一个新的镜像。
docker commit -m "Adding backend code and setup" -a "Your Name" base_jdk_container your-backend-image-name:v1
这里,-m 参数后面是提交信息,描述了这次提交做了哪些更改;-a 是作者信息;base_jdk_container 是你要提交的容器的名称或ID;your-backend-image-name:v1 是新镜像的名字和标签。
第三步:运行新镜像的容器
提交后,你可以基于新创建的镜像运行容器,就像之前提到的一样:
docker run -p 8080:8080 -d your-backend-image-name:v1
注意点
持久化配置和数据:使用 docker commit 方式创建镜像时,所有对容器的修改都会被保存,包括可能的临时文件和缓存。因此,推荐在提交前清理不必要的更改,保持镜像的干净和高效。
可维护性和重复性:虽然 docker commit 能快速基于现有容器创建新镜像,但这种方法不如使用 Dockerfile 来得灵活和易于维护,特别是当需要自动化构建过程或在团队间共享时。Dockerfile 提供了一种更标准化、可复现的方式构建镜像。
总之,虽然可以通过docker commit 快速实现,但为了长远考虑推荐使Dockerfile 方法来构建包含后端代码服务的容器,因为它提供了更好的版本控制、可读性和可维护性。
1.8 导出镜像
1.8.1 使用docker save
docker save 命令用于导出 Docker 镜像到一个 tar 文件中,这个文件包含了镜像的所有层、元数据和历史记录,非常适合用于备份或迁移镜像到其他没有网络连接的环境。
docker save -o <output_file.tar> <image_name[:tag]>
-o 或 --output 指定了输出的 tar 文件路径。
<image_name[:tag]> 是你要导出的镜像名和可选的标签。
示例:
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
jdk17_js latest d337aafb770d 18 hours ago 522MB
docker save -o jdk17_js_export_by_save.tar jdk17_js:latest
默认情况下,docker save 不会对输出的文件进行 gzip 压缩。如果需要压缩
docker save -o jdk17_js_export_by_save.tar 【506M】 jdk17_js:latest && gzip jdk17_js_export_by_save.tar
ls -lah
上面的后缀名变成 jdk17_js_export_by_save.tar.gz 【246M】
gunzip jdk17_js_export_by_save.tar.gz
ls -lah
上面的后缀名变成 jdk17_js_export_by_save.tar 【506M】
1.8.2 使用docker export
docker export 命令与 docker save 不同,它是用来导出运行中容器的文件系统快照到一个 tar 文件中,而不是整个镜像。这意味着它不包含镜像的元数据或历史记录,只包含容器运行时的文件系统状态。
docker export <container_id> > <output_file.tar>
<container_id> 是容器的ID或名称。
> 是重定向符号,用于将输出写入文件。
docker export jdk17_js > jdk17_js_export_by_export.tar
gzip jdk17_js_export_by_export.tar 【如果需要压缩,参参考 1.7.1】
总结
如果想要备份整个镜像,包括其历史记录和元数据,应该使用 docker save。
如果你只是想导出某个容器当前的文件系统状态,而不关心镜像的历史或其他元数据,那么使用docker export 更合适。
根据你的需求选择合适的方法来导出 Docker 镜像或容器。
1.9 导入镜像
ls -lah
-rw-r--r-- 1 root root 219 Jun 14 17:08 Dockerfile
-rw-r--r-- 1 root root 506M Jun 15 11:40 jdk17_js_export_by_export.tar
-rw------- 1 root root 506M Jun 15 11:34 jdk17_js_export_by_save.tar
-rw-r--r-- 1 root root 175M Mar 12 01:59 jdk-17_linux-x64_bin.tar.gz
1.9.1 docker import
docker import my_image.tar my_image:tag
docker import http://example.com/path/to/my_image.tar my_image:tag
tag默认latest
docker import jdk17_js_export_by_save.tar jdk17_js_import_by_import
docker images;
REPOSITORY TAG IMAGE ID CREATED SIZE
jdk17_js_import_by_import latest 6c987a084506 38 seconds ago 531MB
jdk17_js latest d337aafb770d 20 hours ago 522MB
1.9.3 docker load
常用于将之前使用 docker save 命令导出的镜像文件重新加载到Docker环境中,或者在没有网络连接的情况下导入镜像。
docker load [OPTIONS] [-i|–input FILE|–quiet]
选项说明:
-i, --input: 指定要加载的tar文件路径。如果不使用此选项,Docker会从标准输入读取数据。
–quiet, -q: 安静模式,减少输出信息。
docker load -i jdk17_js_export_by_save.tar
另外还可以通过下面2个方法加载镜像
docker load < jdk17_js_export_by_save.tar
cat jdk17_js_export_by_save | docker load
需要注意的是,docker load 会把tar文件中的所有镜像层和元数据都加载进本地存储,这可能会占用大量磁盘空间。此外,与 docker import 不同,docker load 会保留原有镜像的层结构和历史信息,更适合于备份和恢复完整的镜像数据。
docker import 和 docker load都是用来将外部的文件导入到 Docker 中成为镜像,但它们之间存在一些关键的区别:
- 功能用途不同
-
docker import
主要用于从一个tar文件(通常包含一个已打包的根文件系统或一个已安装的应用程序)创建一个新的Docker镜像。这个命令不保留原有的层结构,即使导入的tar文件来源于一个Docker导出的镜像,生成的新镜像也会被视为一个单一的层,这可能导致镜像体积较大且缺乏版本控制的透明度。常用于快速导入一个现有的根文件系统或备份文件Docker中。
-
docker load
专门用于从 Docker 镜像的导出文件(由 docker save 命令创建的.tar文件)中加载镜像到本地镜像库。它会重建镜像的多层结构和历史记录,保持与原镜像相同的层和元数据信息,这对于备份和恢复镜像、保留镜像构建历史非常重要。适合于在没有网络连接的环境下导入镜像,或是迁移和分享完整的 Docker 镜像。
-
输入文件类型
docker import通常接收任何类型的tar文件,包括但不限于原始的Docker镜像导出文件。
docker load则专门处理由docker save生成的包含完整镜像层信息的tar文件。
-
对镜像历史的影响
使用 docker import创建的镜像通常只有单一层,丢失了原镜像的构建历史和层次结构,不利于版本追踪和优化。
docker load 保留了镜像的多层结构和构建历史,更适合于维护和管理。
总结来说,如果你需要从一个包含应用程序或文件系统的tar文件创建一个简单的Docker镜像,可以使用 docker import。而当你需要恢复或迁移一个之前通过 docker save 导出的完整Docker镜像时,应该使用 docker load,以保持镜像的所有特性不变。
1.9.3 docker pull
从Docker registry(默认通常是 Docker Hub)下载镜像
docker pull [选项] [仓库名[:标签]]
docker pull ubuntu
docker pull nginx:1.19
测试pull nginx:
docker pull nginx:1.19
1.19: Pulling from library/nginx
69692152171a: Pulling fs layer
49f7d34d62c1: Pulling fs layer
69692152171a: Pull complete
49f7d34d62c1: Pull complete
5f97dc5d71ab: Pull complete
cfcd0711b93a: Pull complete
be6172d7651b: Pull complete
de9813870342: Pull complete
Digest: sha256:df13abe416e37eb3db4722840dd479b00ba193ac6606e7902331dcea50f4f1f2
Status: Downloaded newer image for nginx:1.19
运行nginx
docker run --name nginx_js -p 8080:80 -d nginx:1.19
【8080宿主机,80容器,:前面宿主机,后面的容器】
docker ps -a
验证nginx的访问
curl http://localhost:8080
<!DOCTYPE html>
<html>
......
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
另外可以增加-v等参数:
将宿主机的目录或文件挂载到容器内部的指定路径。这对于让容器访问宿主机上的数据、配置文件或代码等非常有用。
这有助于保持数据持久化,即使容器被删除,数据依然存在宿主机上
docker run -v <宿主机路径>:<容器内路径> [其他选项] <镜像名>
如果需要将宿主机的 /my/nginx/conf 目录挂载到容器内的 /etc/nginx/conf.d,以便使用自定义的 Nginx 配置文件
docker stop nginx_js
【run是执行 创建 容器,所以实际不能重复执行,需要先rm移除,rm不会删除镜像,可通过docker images查看镜像,如果需要删除镜像,】
docker rm -f nginx_js
docker run --name nginx_js -p 8080:80 -d -v /usr/local/nginx/conf:/etc/nginx/conf.d nginx:1.19
【:前面宿主机,后面的容器】
1.10 查看docker中服务日志
如果是跑java jar服务,还未验证jar包日志能不能通过docker logs查看,还是需要docker exec 进入容器看?
AI解读
无论是运行普通的 Java 应用还是 Java JAR 包服务,只要你没有特别配置将日志输出重定向到其他地方(比如文件或外部服务),Docker 容器的标准输出(stdout)和标准错误(stderr)默认会捕获应用的输出,这意味着你完全可以通过 docker logs 命令查看 Java 应用(包括 JAR 包服务)的启动日志和运行时日志。因此,直接使用 docker logs 命令应该是足够的,不需要额外 docker exec 进入容器查看。
docker logs nginx_js
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: /etc/nginx/conf.d/default.conf is not a file or does not exist
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2024/06/15 05:19:37 [emerg] 1#1: "load_module" directive is not allowed here in /etc/nginx/conf.d/nginx.conf:2
nginx: [emerg] "load_module" directive is not allowed here in /etc/nginx/conf.d/nginx.conf:2
通过curl http://localhost:8080测试,并未启动,说明这里的宿主机上config中具体相关路径和文件并不全。
继续去掉-v验证日志
docker rm -f nginx_js
docker run --name nginx_js -p 8080:80 -d nginx:1.19
docker logs nginx_js
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
curl http://localhost:8080 测试访问正常
持续滚动显示日志
docker logs -f nginx_js
持续滚动显示日志最后50条日志并带上时间
docker logs --tail 50 --follow --timestamps nginx_js
1.11 自动重启容器
如果需要在容器退出后自动重启它,可以在创建容器时使用 --restart 参数。有几种重启策略可选:
no:容器不会自动重启(默认)。
on-failure:仅在容器非正常退出(非0退出码)时重启。
always:无论退出状态如何,容器都会被重启。
unless-stopped:容器总是重启,除非它被手动停止。
例如,创建一个始终自动重启的容器:
docker rm -f nginx_js
docker run --name nginx_js -p 8080:80 -d -v /usr/local/nginx/conf:/etc/nginx/conf.d --restart always nginx:1.19
上面的配置并不能成功启动,但是会创建容器,并会不断重启
docker ps -a | grep nginx_js
a1371cbbf70b nginx:1.19 "/docker-entrypoint.…" 2 minutes ago Restarting (1) 51 seconds ago nginx_js
docker rm -f nginx_js
docker run --name nginx_js -p 8080:80 -d --restart always nginx:1.19
1.12 docker-compose
这里暂时跳过练习,后期遇到补充
《docker-compose教程(安装,使用, 快速入门)》
https://blog.csdn.net/m0_37899908/article/details/131268835
Docker Compose 是 Docker 官方提供的一种工具,用于定义和运行多容器 Docker 应用程序。通过 Docker Compose,用户可以使用 YAML 文件来配置应用程序需要的所有服务,然后使用一个命令来启动并管理整个服务堆栈,极大地简化了容器化应用的部署和维护过程。
基本概念
YAML 文件:Docker Compose 使用一个名为 docker-compose.yml 的文件来定义服务、网络和卷等应用组件及其配置。
服务:在 Compose 文件中定义的每个服务都对应一个 Docker 容器,可以配置镜像、环境变量、端口映射、依赖关系等。
命令:Docker Compose 提供了一系列命令,如 up、down、build、run 等,用于管理服务的生命周期。
常用命令
docker-compose up:创建并启动 Compose 文件中定义的所有服务。如果服务已经存在,则会尝试重新创建服务(除非使用 --no-recreate 参数)。
docker-compose down:停止并移除 Compose 项目中所有的容器、网络、卷和镜像(默认情况下仅移除容器和网络)。
docker-compose build:构建服务所依赖的镜像。
docker-compose ps:列出项目中所有的容器。
docker-compose run:在一个一次性的容器中运行服务的命令,该容器会在命令执行完毕后被删除。
示例
一个简单的 docker-compose.yml 文件示例,用于定义一个 Web 服务和一个数据库服务:
version: '3'
services:
web:
image: nginx:latest
ports:
- "80:80"
db:
image: postgres:latest
environment:
POSTGRES_PASSWORD: example
在这个示例中,定义了两个服务:一个是使用最新 Nginx 镜像的 Web 服务,公开了宿主机的 80 端口到容器的 80 端口;另一个是使用最新 PostgreSQL 镜像的数据库服务,并设置了环境变量 POSTGRES_PASSWORD。
通过在包含此 docker-compose.yml 文件的目录下运行 docker-compose up,Docker Compose 将自动创建和启动这两个服务,构建必要的网络连接,使得 Web 服务可以访问数据库服务。
Docker Compose 是进行多容器应用开发、测试和部署的强大工具,特别是在微服务架构中。
2.windows环境
这里暂时跳过练习,后期遇到补充