What: 什么是构建docker镜像?java
构建docker镜像在现有镜像的基础上,修改或添加我的的功能后,从新打包成新镜像的过程git
Why: 为何要构建docker镜像?github
docker镜像方便部署及分享他人docker
mkdir demo01-helloworld cd demo01-helloworld
Docker以文件Dockerfile
做为配置文件,内容以下shell
Dockerfileapache
FROM ubuntu:latest CMD ["/bin/echo", "Hello world!"]
以上内容很是简单ubuntu
FROM
用来配置基础镜像,这里以ubuntu的最新版本的镜像做为基础镜像CMD
表示镜像中执行的命令,这里等同于执行命令/bin/echo "Hello World!"
命令数组
docker image build . -t demo01-helloworld:0.0.1
.
表示当前文件夹里的全部文件eclipse
-t
等同于--tag
,做用是给镜像打标签,这里的标签名为demo01-helloworld
maven
:
后是镜像的版本号,若是省略则默认为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启动时先判断有没有该容器,若是不存在则经过镜像建立相应的容器,而后执行容器
须要说明的是CMD
能够在构造镜像的时候不指定,启动容器的时候执行。若是启动时指定了命令,则CMD
中指定的命令将不会执行,即被覆盖,现象以下。你看懂了吗?
$ docker container run demo01-helloworld:0.0.1 /bin/echo "Hello world! v2" Hello world! v2
mkdir demo02-hellojava cd demo02-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
在打包以前先肯定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!
如前文所述构建镜像须要一个基础镜像,基础镜像也能够不提早拉取,构建的时候若是不存在也会自动拉取
该例子中要想启动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,即伪终端建立配置文件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!
命令 | 功能 |
---|---|
FROM | 指定基础镜像 |
COPY | 复制文件或文件夹 |
ENV | 设置环境变量 |
RUN | 执行一个命令,能够写多个,一般用于安装软件包 |
CMD | 执行一个命令,只有一个被执行,可被docker run后面的命令所覆盖,即若是命令行中有该命令,CMD中的将不会执行 |
ENTRYPOINT | 配置容器启动时的命令,必定会执行 |
EXPOSE | 暴露的端口号 |