docker构建镜像
1 What & Why
What: 什么是构建docker镜像?
构建docker镜像在现有镜像的基础上,修改或添加个人的功能后,重新打包成新镜像的过程
Why: 为什么要构建docker镜像?
docker镜像方便部署及分享他人
2 Hello World
2.1 目标
- 利用现有镜像ubuntu构建新镜像
- 镜像的功能是利用ubuntu的echo命令打印Hello world
2.2 创建文件夹
mkdir demo01-helloworld
cd demo01-helloworld
2.3 创建配置文件
Docker以文件Dockerfile
作为配置文件,内容如下
Dockerfile
FROM ubuntu:latest
CMD ["/bin/echo", "Hello world!"]
以上内容非常简单
-
FROM
用来配置基础镜像,这里以ubuntu的最新版本的镜像作为基础镜像 -
CMD
表示镜像中执行的命令,这里等同于执行命令/bin/echo "Hello World!"
- 当前的格式为Exec格式
- 后面会介绍shell格式
2.4 构建镜像
命令
docker image build . -t demo01-helloworld:0.0.1
-
.
表示当前文件夹里的所有文件 -
-t
等同于--tag
,作用是给镜像打标签,这里的标签名为demo01-helloworld
-
:
后是镜像的版本号,如果省略则默认为latest
构建过程如下,当打印Successfully tagged demo01-helloworld:0.0.1
表明镜像构建成功
$ docker image build . -t demo01-helloworld
Sending build context to Docker daemon 2.048kB
Step 1/2 : FROM ubuntu:latest
---> 4e2eef94cd6b
Step 2/2 : CMD ["/bin/echo", "Hello world!"]
---> Running in 581995f3af46
Removing intermediate container 581995f3af46
---> afa0f6e8fc94
Successfully built afa0f6e8fc94
Successfully tagged demo01-helloworld:0.0.1
可以用命令docker image ls
查询所有镜像,再次确认已经构建完成
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
demo01-helloworld 0.0.1 afa0f6e8fc94 19 seconds ago 73.9MB
运行镜像,先生成容器,再启动容器
$ docker container run demo01-helloworld:0.0.1
Hello world!
docker启动时先判断有没有该容器,如果不存在则通过镜像创建相应的容器,然后执行容器
2.5 注意
需要说明的是CMD
可以在构造镜像的时候不指定,启动容器的时候执行。如果启动时指定了命令,则CMD
中指定的命令将不会执行,即被覆盖,现象如下。你看懂了吗?
$ docker container run demo01-helloworld:0.0.1 /bin/echo "Hello world! v2"
Hello world! v2
3 java应用
3.1 目标
- 利用现有镜像openjdk构建新镜像
- 镜像的功能是运行java程序打印Hello java
3.2 创建文件夹
mkdir demo02-hellojava
cd demo02-java
3.3 创建java工程
选择你喜欢的方式创建一个maven工程,可以从通过网页下载模板,可以利用eclipse和idea等等
这里采用mvn命令的方式创建
mvn archetype:generate -DgroupId=org.zwx.hellojava -DartifactId=demo02-hellojava -DinteractiveMode=false
结果如下
$ mvn archetype:generate -DgroupId=org.zwx.hellojava -DartifactId=demo02-hellojava -DinteractiveMode=false
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------< org.apache.maven:standalone-pom >-------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] --------------------------------[ pom ]---------------------------------
[INFO] ...省略一些内容
[INFO] Parameter: basedir, Value: /Users/zhouweixin/docker-demos
[INFO] Parameter: package, Value: org.zwx.hellojava
[INFO] Parameter: groupId, Value: org.zwx.hellojava
[INFO] Parameter: artifactId, Value: demo02-hellojava
[INFO] Parameter: packageName, Value: org.zwx.hellojava
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] project created from Old (1.x) Archetype in dir: /Users/zhouweixin/docker-demos/demo02-hellojava
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 16.557 s
[INFO] Finished at: 2020-09-28T17:55:09+08:00
[INFO] ------------------------------------------------------------------------
文件目录
.
├── pom.xml
└── src
├── main
│ └── java
│ └── org
│ └── zwx
│ └── hellojava
│ └── App.java
└── test
└── java
└── org
└── zwx
└── hellojava
└── AppTest.java
3.4 编译执行
在打包之前先确定java应用可以正常执行
首先,修改文件src/main/java/org/zwx/hellojava/App.java
package org.zwx.hellojava;
/**
* Hello world!
*
*/
public class App
{
public static void main( String[] args )
{
System.out.println( "Hello java!" );
}
}
然后,用mvn
命令编译打包
$ mvn package
[INFO] Scanning for projects...
[INFO]
[INFO] -----------------< org.zwx.hellojava:demo02-hellojava >-----------------
[INFO] Building demo02-hellojava 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] ...省略一些内容
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ demo02-hellojava ---
[INFO] Building jar: /Users/zhouweixin/docker-demos/demo02-hellojava/target/demo02-hellojava-1.0-SNAPSHOT.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.531 s
[INFO] Finished at: 2020-09-28T17:59:40+08:00
[INFO] ------------------------------------------------------------------------
文件目录
.
├── pom.xml
├── src
│ └── ...省略一些内容
└── target
├── demo02-hellojava-1.0-SNAPSHOT.jar
└── ...省略一些内容
当你执行完命令mvn package
后,首先会编译生成一些class文件,然后打包成demo02-hellojava-1.0-SNAPSHOT.jar
,生成的文件都在目录target下
该jar文件是执行文件,具体执行命令如下
$ java -cp target/demo02-hellojava-1.0-SNAPSHOT.jar org.zwx.hellojava.App
Hello java!
3.5 拉取基础镜像
如前文所述构建镜像需要一个基础镜像,基础镜像也可以不提前拉取,构建的时候如果不存在也会自动拉取
该例子中要想启动java应用,你知道需要哪个环境吗?
你应该是猜对了,仅仅需要java的运行时环境(jre)
首先到hub.docker.com上检索jre的相关tag,这里我们选择的是8u265-jre
二话不说,先拉取镜像(也可以不提前拉取)
$ docker pull openjdk:8u265-jre
8u265-jre: Pulling from library/openjdk
57df1a1f1ad8: Pull complete
71e126169501: Pull complete
1af28a55c3f3: Pull complete
a9777c2d5c29: Pull complete
9248106993db: Pull complete
1f74ab5b5b3e: Pull complete
Digest: sha256:e98dece4606dc1ec47c0c9ab6aa43931577232a5b7d6fd46f3ead7377727b412
Status: Downloaded newer image for openjdk:8u265-jre
docker.io/library/openjdk:8u265-jre
用交互的方式运行该镜像并确定java的版本
$ docker container run -it openjdk:8u265-jre
root@0687c67dccd0:/# java -version
openjdk version "1.8.0_265"
OpenJDK Runtime Environment (build 1.8.0_265-b01)
OpenJDK 64-Bit Server VM (build 25.265-b01, mixed mode)
参数说明
-
-it
是-i
和-t
的缩写 -
-i
全称是--interactive
,即交互模式,可以正常的输入输出 -
-t
是一个伪TTY,即伪终端
3.6 构建镜像
创建配置文件Dockerfile
FROM openjdk:8u265-jre
COPY target/demo02-hellojava-1.0-SNAPSHOT.jar /usr/src/demo02-hellojava-1.0-SNAPSHOT.jar
CMD java -cp /usr/src/demo02-hellojava-1.0-SNAPSHOT.jar org.zwx.hellojava.App
参数说明
-
COPY
命令用于将本地文件拷贝到基础镜像中,并且这个基础镜像中有java运行时环境,两者结合满足正常运行程序- 第一个参数为本地文件目录
- 第二个参数为基础镜像中的目录
-
CMD
命令表示在基础镜像中执行的命令(可以不写数组的形式)
执行镜像构建命令
$ docker image build . -t demo02-hellojava:0.0.1
Sending build context to Docker daemon 38.91kB
Step 1/3 : FROM openjdk:8u265-jre
---> d9d1d3243082
Step 2/3 : COPY target/demo02-hellojava-1.0-SNAPSHOT.jar /usr/src/demo02-hellojava-1.0-SNAPSHOT.jar
---> Using cache
---> 6c34d345bb51
Step 3/3 : CMD java -cp /usr/src/demo02-hellojava-1.0-SNAPSHOT.jar org.zwx.hellojava.App
---> Running in 0d9a33ea0ae1
Removing intermediate container 0d9a33ea0ae1
---> fc3cd9ee5218
Successfully built fc3cd9ee5218
Successfully tagged demo02-hellojava:0.0.1
启动
$ docker container run demo02-hellojava:0.0.1
Hello java!
4 Dockfile中的命令
命令 | 功能 |
---|---|
FROM | 指定基础镜像 |
COPY | 复制文件或文件夹 |
ENV | 设置环境变量 |
RUN | 执行一个命令,可以写多个,通常用于安装软件包 |
CMD | 执行一个命令,只有一个被执行,可被docker run后面的命令所覆盖,即如果命令行中有该命令,CMD中的将不会执行 |
ENTRYPOINT | 配置容器启动时的命令,一定会执行 |
EXPOSE | 暴露的端口号 |