原创

运维-docker专题-创建镜像-操作容器-制作jdk17的docker镜像等

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

-o 或 --output 指定了输出的 tar 文件路径。

是你要导出的镜像名和可选的标签。

示例:

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 中成为镜像,但它们之间存在一些关键的区别:

  1. 功能用途不同

    • docker import

      主要用于从一个tar文件(通常包含一个已打包的根文件系统或一个已安装的应用程序)创建一个新的Docker镜像。这个命令不保留原有的层结构,即使导入的tar文件来源于一个Docker导出的镜像,生成的新镜像也会被视为一个单一的层,这可能导致镜像体积较大且缺乏版本控制的透明度。常用于快速导入一个现有的根文件系统或备份文件Docker中。

    • docker load

      专门用于从 Docker 镜像的导出文件(由 docker save 命令创建的.tar文件)中加载镜像到本地镜像库。它会重建镜像的多层结构和历史记录,保持与原镜像相同的层和元数据信息,这对于备份和恢复镜像、保留镜像构建历史非常重要。适合于在没有网络连接的环境下导入镜像,或是迁移和分享完整的 Docker 镜像。

  2. 输入文件类型

    docker import通常接收任何类型的tar文件,包括但不限于原始的Docker镜像导出文件。

    docker load则专门处理由docker save生成的包含完整镜像层信息的tar文件。

  3. 对镜像历史的影响

    使用 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环境

这里暂时跳过练习,后期遇到补充

正文到此结束
本文目录