构建docker镜像有两种方式:commit和DockerFile。commit方式构造的镜像对用户不透明,你不知道作者在父镜像基础上做了什么改动。DockerFile的方式符合Infrastructure As Code的思想,通过这份文件你清楚的知道作者对父镜像做的变动。
用DockerFile文件构建docker镜像
一 demo程序
class HelloDocker {
public static void main(String[] args) {
System.out.println("Hello Docker!");
}
}
二 构建一个DockerFile
DockerFile的默认文件名就是DockerFile, 如果用其他的名字,build的时候就需要加-f参数指定。先看一个demo
# Use java 8 as a parent image
FROM java:8
MAINTAINER ruzun "***@qq.com"
ENV appRoot="/home/admin/docker" \
version="2.0"
WORKDIR $appRoot
# Set the working directory to /app
COPY ["HelloDocker.java", "start.sh", "$appRoot/"]
VOLUME ["/var"]
RUN chmod -R 777 $appRoot
RUN javac $appRoot/HelloDocker.java
ENTRYPOINT ["/home/admin/docker/start.sh"]
- DockerFile的第一行必须是FROM指令,指定父镜像。这里我用的是java仓库的版本8。仓库地址 https://hub.docker.com/r/library/java/
- MAINTAINER : 指令指定维护者的信息
- ENV : 设置环境变量,环境变量可以给后面的指令使用
- WORKDIR : 指定工作路径,如果不存在则会创建
- COPY : 从当前系统拷贝文件到指定路径(最后一个参数)。Copy指令有个特性,任何被复制的文件的权限都会被置为root用户。所以用chmod命令修改权限
- RUN : 执行shell脚本,RUN指令都会以/bin/sh -c来包装执行。
- CMD : 在容器启动后启动一个进程
- ENTRYPOINT: 容器进入点
三 start.sh脚本
#!/bin/bash
java HelloDocker
#!/bin/bash 这行用于告诉内核用哪个解释器来执行脚本,一定要加
四 镜像构建
docker build --no-cache=true -t hellodocker .
-t 参数指定镜像名是hellodocker, 没有指定版本号则默认是latest。这个命令最后有一个“.”, 如果没写,会执行失败。
五 查看本机已有的镜像:
~ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hellodocker latest f6f5de500dee 21 minutes ago 643MB
ruzun_image 1.1 c3f64fa89d3e 8 days ago 220MB
ruzun_image 1.0 1ce98f043c07 8 days ago 123MB
ruzun_image latest 016508e46f4f 8 days ago 123MB
ubuntu latest 20c44cd7596f 2 weeks ago 123MB
ubuntu 18.04 66a5a351d4ab 2 weeks ago 85.6MB
至此,镜像已经构造好了, 可以看到hellodocker已经在本地了
六 运行镜像
运行命令:
docker run hellodocker
Hello Docker!
七 Dockerfile文件的执行流程详解
- 从基础镜像运行一个容器
- 执行一条指令
- 提交一个新的镜像层
- 基于刚才的镜像层构建一个新容器
- 执行下一条指令,直到所有指令执行完毕
~ docker build --no-cache=true -t hellodocker .
Sending build context to Docker daemon 5.12kB
Step 1/8 : FROM java:8
---> d23bdf5b1b1b
Step 2/8 : MAINTAINER ruzun "***@qq.com"
---> Running in a45ce42dff9e
---> 4ef53845d4d1
Removing intermediate container a45ce42dff9e
Step 3/8 : ENV appRoot "/home/admin/docker" version "2.0"
---> Running in be07472d284f
---> 45825bf24324
Removing intermediate container be07472d284f
Step 4/8 : WORKDIR $appRoot
---> 99d750cbf3ea
Removing intermediate container 97d676082f70
Step 5/8 : COPY HelloDocker.java start.sh $appRoot/
---> 26cb0722a2ac
Step 6/8 : RUN chmod -R 777 $appRoot
---> Running in 5738b7cbd749
---> 82943d6b1237
Removing intermediate container 5738b7cbd749
Step 7/8 : RUN javac $appRoot/HelloDocker.java
---> Running in e4c80e8af566
---> 5297d71819d4
Removing intermediate container e4c80e8af566
Step 8/8 : CMD java HelloDocker
---> Running in fc3a19b9da11
---> f6f5de500dee
Removing intermediate container fc3a19b9da11
Successfully built f6f5de500dee
Successfully tagged hellodocker:latest
每条命令执行完之后,就会显示“Removing intermediate container containerId”, 删除中间容器,然后构建一个新的容器