Docker笔记(五):整一个自己的镜像
原文地址:http://blog.jboost.cn/docerk-5.html
获取镜像的途径有两个,一是从镜像仓库获取,如官方的Docker Hub,二是自定义。上文已经介绍如何从镜像仓库获取镜像,本文基于一个Springboot项目,来介绍自定义一个镜像的基本流程。
1. 定制镜像的本质
我们知道镜像是分层存储的,镜像的构建也是一层一层进行的,一层构建完后,就变为只读,在其上再构建下一层。因此定制镜像,实际上就是定义每一层要干的事,比如执行某个命令,设置一个环境变量,声明一个暴露端口等等。然后在构建时,按照各层的定义,一层一层地完成构建,最终形成一个包含这些层的镜像。
2. Dockerfile文件
Docker中定义各层要干的事的文件叫Dockerfile,它是一个文本文件,包含了一条条的指令,每一条指令对应一层镜像,指令的内容就描述了这一层该如何构建。如下示例了一个非常简单的Dockerfile,
FROM nginx
RUN echo '<h1>Hello jboost!</h1>' > /usr/share/nginx/html/index.html
我们定制镜像,必须要以某一个镜像为基础,在其上构建自己需要的层,如上示例中,我们是以nginx镜像为基础,然后在第二层定制了我们自己的内容——修改index.html的内容为<h1>Hello jboost!</h1>,这样运行容器打开nginx主页时就不会显示默认的页面内容了。
上面示例中接触了Dockerfile的两个指令
- FROM:FROM指令指定基础镜像,每一个定制镜像必须要有一个基础镜像,所以必须要有一条FROM指令,并且是Dockerfile的第一条指令
- RUN:RUN指令指定需要执行的命令,后面接的命令就像是shell脚本一样可执行
Dockerfile还提供了许多其它指令,后续我们再集中介绍,本文只对接触到的指令做简单说明。
3. 自定义一个镜像
这部分以一个Springboot项目为基础,介绍自定义一个镜像涉及的基本环节。项目地址为:https://github.com/ronwxy/swagger-register ,该项目是一个Swagger API文档注册服务,其它项目可将Swagger API信息注册到该服务,进行统一查看与管理。
3.1 定义Dockerfile文件
首先,我们在项目的根目录下创建一个Dockerfile文件(文件名就叫Dockerfile),其内容为:
FROM openjdk:-jdk-alpine
ENV PROFILE=dev
RUN mkdir /app /logs
COPY ./target/swagger-register-1.0.-SNAPSHOT.jar /app/app.jar
WORKDIR /app
VOLUME /register-data
EXPOSE
CMD ["java", "-Dspring.profiles.active=${PROFILE}", "-jar", "app.jar"]
从上往下依次介绍如下
- 第一行:FORM openjdk:8-jdk-alpine, 表示以
openjdk:8-jdk-alpine这个镜像为基础镜像,因为这是一个Springboot项目所以必须要有jdk支持,我们在定制镜像时,可以找一个最适合的镜像作为基础镜像。 - 第二行:ENV PROFILE=dev, 定义了一个环境变量,这个环境变量可以在后面被引用
- 第三行:RUN mkdir /app /logs,通过mkdir命令创建了两个目录,用来保存jar执行文件及日志
- 第四行:COPY ./target/swagger-register-1.0.0-SNAPSHOT.jar /app/app.jar 将target目录下的jar包复制到/app目录下,并且进行重命名
- 第五行:WORKDIR /app, 指定工作目录为/app,后面各层的当前目录就是指定的工作目录
- 第六行:VOLUME /register-data, 定义一个匿名数据卷,前面说过写操作不要直接在容器内进行,而要改为写挂载的数据卷目录,这个定义可在运行容器时通过 -v 来覆盖。
- 第七行:EXPOSE 11090, 声明了运行容器时提供的服务端口,也仅仅是个声明而已,只是告诉使用的人要映射这个端口,通过 -p 可映射端口。
- 第八行:CMD [“java”, “-Dspring.profiles.active=${PROFILE}”, “-jar”, “app.jar”], 指定了容器启动命令,因为是一个Springboot项目,所以就是一个java -jar的执行命令,容器启动的时候就会执行该命令来运行Springboot服务,这里引用了第二行定义的环境变量PROFILE
3.2 配置maven插件
定义好Dockerfile后,为了方便构建镜像,我们可以借助maven的dockerfile插件dockerfile-maven-plugin,在pom.xml的build部分加入配置如下
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- Docker maven plugin -->
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>1.4.</version>
<configuration>
<repository>${docker.image.prefix}/${project.artifactId}</repository>
<buildArgs>
<JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
</buildArgs>
</configuration>
</plugin>
<!-- Docker maven plugin -->
</plugins>
</build>
repository指定了镜像的名称,docker.image.prefix需要properties部分进行定义,我这里是springboot。
3.3 构建镜像
下载源码:https://github.com/ronwxy/swagger-register.git ,然后在项目的根目录下执行如下命令(前提是本地已经装好了docker与maven及jdk)
mvn clean package -Dmaven.test.skip=true dockerfile:build
该命令首先会执行mvn clean package -Dmaven.test.skip=true对项目进行打包,生成./target/swagger-register-1.0.0-SNAPSHOT.jar文件,然后基于当前目录下的Dockerfile文件进行构建,如下图所示

由上图可看出,该镜像构建分八步(对应Dockerfile的八行指令),每一步生成一个镜像层,每一层都有唯一的ID。由图中也可以看出,除了COPY之类的命令外,每一层的构建实际上是先基于上一层启动一个容器,然后执行该层定义的操作,再移除这个容器来实现的,如第八步中
Step / : CMD ["java", "-Dspring.profiles.active=${PROFILE}", "-jar", "app.jar"]
[INFO]
[INFO] ---> Running in f4acd0b53bca
[INFO] Removing intermediate container f4acd0b53bca
[INFO] ---> a9ee579f2d62
先启动一个ID为f4acd0b53bca的容器,在其中执行CMD所定义的命令,然后再移除容器f4acd0b53bca,最后生成ID为a9ee579f2d62的镜像。
构建完后,我们就可以在本地镜像中通过docker iamges看到我们定制的镜像了,如图
图中springboot/swagger-register镜像即为我们刚刚构建好的定制镜像。
3.4 启动容器
我们可以通过以下命令来启动一个刚才定制镜像的容器
docker run -d --name swagger-register -p : -v /home/jenkins/swagger-register/register-data:/register-data -v /home/jenkins/swagger-register/logs:/logs --restart=always springboot/swagger-register:latest
其中:
- -d 表示以后台进程方式运行
- –name 指定容器名称
- -p 指定端口映射,左边为宿主机端口,右边为容器服务端口
- -v 指定数据卷挂载,左边为宿主机目录,右边为容器目录
- –restart=always 表示在docker启动时自动启动该容器
关于容器相关的内容后面详细介绍,这里不展开说明了。启动容器后, 我们就可以浏览器打开地址 http://宿主机ip:11090/doc.html 来访问服务了(打开页面后内容是空的,因为没有任何服务注册Swagger API, 相关内容可参考 swagger api文档集中化注册管理)
4. 总结
本文介绍了一个基于Springboot项目的Docker镜像定制及使用过程,对镜像的构建过程,及Dockerfile的基本指令以及容器的运行做了基本介绍。后续会对Dockerfile的其它指令及Dockerfile的一些最佳实践进行更为详细的介绍,欢迎关注。
我的个人博客地址:http://blog.jboost.cn
我的微信公众号:jboost-ksxy (一个不只有技术干货的公众号,欢迎关注,及时获取更新内容)
—————————————————————————————————————————————————————
Docker笔记(五):整一个自己的镜像的更多相关文章
- Docker | 第五章:构建自定义镜像
前言 上一章节,主要是介绍了下Dockerfile的一些常用命令的说明.我们知道,利用Dockerfile可以构建一个新的镜像,比如运行Java环境,就需要一个JDK环境的镜像,但直接使用公共的镜像时 ...
- 【opencv学习笔记五】一个简单程序:图像读取与显示
今天我们来学习一个最简单的程序,即从文件读取图像并且创建窗口显示该图像. 目录 [imread]图像读取 [namedWindow]创建window窗口 [imshow]图像显示 [imwrite]图 ...
- Docker笔记01-发布一个dotnetcore应用
OS:Widows 10 IDE: VS2017 Docker:Docker Desktop for Windows Windows下安装Docker需要先启用Hyper-v 在Windows 容器的 ...
- docker 笔记(3)第一个dockerfile
#vim Dockerfile FROM ubuntu RUN apt-get update && apt-get install -y vim #docker build -t ub ...
- Docker笔记(八):数据管理
前面(哪个前面我也忘了)有说过,如果我们需要对数据进行持久化保存,不应使其存储在容器中,因为容器中的数据会随着容器的删除而丢失,而因通过将数据存储于宿主机文件系统的形式来持久化.在Docker容器中管 ...
- Docker笔记(九):网络管理
Docker的应用运行在容器中,其相互之间或与外部之间是如何通信的,涉及到哪些知识点,本文对相关内容进行整理.因网络这块牵涉的面较多,因此只从日常使用或理解的角度出发,过于专业的就不深入探讨了. 1. ...
- Docker笔记(十一):Dockerfile详解与最佳实践
Dockerfile是一个文本文件,包含了一条条指令,每条指令对应构建一层镜像,Docker基于它来构建一个完整镜像.本文介绍Dockerfile的常用指令及相应的最佳实践建议. 1. 理解构建上下文 ...
- Docker 笔记学习
文章目录 概述 CentOS7 Docker 安装 启动 Docker 后台服务 镜像加速 Docker常用命令 如何创建一个镜像 存储和载入镜像 上传镜像 容器的基本操作 创建容器 终止容器 如何进 ...
- docker学习笔记6:利用dockerfile创建镜像介绍(生成简单web服务器镜像)
本文介绍如何利用dockerfile来创建镜像.下面介绍具体的操作过程: 一.创建构建环境 操作示例如下: xxx@ubuntu:~$ pwd /home/xxx xxx@ubuntu:~$ mkdi ...
随机推荐
- 基于Spring开发
1. XML Schema 1.1 最简单的标签 一个最简单的标签,形式如: <bf:head-routing key="1" value="1" to= ...
- Unpaired/Partially/Unsupervised Image Captioning
这篇涉及到以下三篇论文: Unpaired Image Captioning by Language Pivoting (ECCV 2018) Show, Tell and Discriminate: ...
- Python写的嗅探器——Pyside,Scapy
使用Python的Pyside和Scapy写的嗅探器原型,拥有基本框架,但是功能并不十分完善,供参考. import sys import time import binascii from PySi ...
- 【必须知道】Enum_Flags
[Flags] enum AnyThings{ A=1, B=2, C=4, D=8 } 枚举赋值必须是2^n才可以,目的是实现他们的二进制表示中的 1 ,不要重叠,如 1=0001 2=0010 ...
- 用Delphi开发视频聊天软件
摘要:目前网上视频聊天软件.视频会议软件.可视IP电话软件随处可见,你是否想自己做一个玩玩?其实这类软件无非是视频加上网络而建成的.如果熟悉视频捕捉和网络传输技术,根本就难不倒你.微软为软件开发人员提 ...
- Windows环境下使用Node.js
作者:短工邦技术部 - 陈文哲 Parse用的就是Node.js,所以我们要先了解什么是Node.js,以及做一些简单的操作. Node.js 的主要思路是:使用非阻塞的,事件驱动的 I/O 操作来保 ...
- Qt 5 最小构建笔记(只编译QtBase)
只想用Qt5最基本的功能,因此只编译QtBase.也不想为了编译一个Qt装很多东西(比如非常肥的DirectX SDK) 软件清单: Visual Studio 2010 Professional w ...
- Qt Style Sheet实践(二):组合框QComboBox的定制(24K纯开源)——非常漂亮
组合框是一个重要且应用广泛的组件,一般由两个子组件组成:文本下拉单部分和按钮部分.在许多既需要用户选择.又需要用户手动输入的应用场景下,组合框能够很好的满足我们的需求.如我们经常使用的聊天软件QQ登录 ...
- Cleanmymac X 4.4.3 激活破解版|兼容mac最新系统-Mac电脑清理工具
CleanMyMac X 4.4.3 激活破解版为最新版清理工具,为你所爱的东西腾出空间.CleanMyMac拥有一系列巧妙的新功能,它可以安全.智能地扫描和清理整个系统,删除大的未使用的文件,卸载不 ...
- SpringBoot整合Redis注意的一些问题
1:ERR value is not an integer or out of range 1-1:背景 使用redisTemplate.opsForValue().increment(key, de ...