首先应该了解Docker镜像的分层机制,这个网上文章很多,简单说就是对镜像的每次修改都是在原镜像基础上加了一层包装;
构建自己的docker镜像有两种方式;
一种是在启动容器后,直接对容器进行操作,然后commit,好处是方便直观,但会导致很多中间层,且不好追溯,所以不推荐这样用;
另一种是编辑dockerfile,然后通过docker build生成镜像,下面详细说说如何使用dockerfile构建一个带jdk的centos镜像;
先准备一个文件夹img,把需要的文件放到子文件夹resource中,这里还拿了一个rpm文件演示如何安装,如下:
img/
├── Dockerfile
└── resource
├── jdk1.7.0_65
├── nc-1.84-22.el6.x86_64.rpm
文件Dockerfile的内容如下:
FROM daocloud.io/centos:latest COPY resource /usr/local RUN cd /usr/local && rpm -ivh nc-1.84-22.el6.x86_64.rpm && yum install which -y && rm -rf nc-1.84-22.el6.x86_64.rpm && yum clean all ENV JAVA_HOME=/usr/local/jdk1.7.0_65/jre ENV CLASSPATH=.:$JAVA_HOME/lib PATH=$JAVA_HOME/bin:$PATH
FROM 必须位于第一行,表示基础镜像,这里为centos,若不需要任何基础环境就用scratch;
COPY 拷贝宿主机的资源到镜像,这里是将resource下所有东西拷贝到镜像的/usr/local/目录;
RUN 镜像中执行命令,这里安装了一个rpm包和yum安装which命令,然后进行了清理;
这里把多个命令合并到一个RUN语句是为了减少层数;
ENV 设置镜像的环境变量,由于后面两个变量依赖JAVA_HOME,所以必须分到两个ENV语句了;
其他命令还有:ADD/CMD/ENTRYPOINT/VOLUME/ARG/EXPOSE/WORKDIR/USER/HEALTHCHECK/ONBUILD等;
下面构建镜像:
# cd img/ # docker build -t my/base . # docker images REPOSITORY TAG IMAGE ID CREATED SIZE my/base latest 2cdd09a142e5 24 seconds ago 359MB daocloud.io/centos latest a8493f5f50ff 4 days ago 192MB
. 命令最后传入的是build的工作目录,这个工作目录是很重要的;
工作目录里所有的文件会传输到docker服务端,而且dockfile中指定文件时(COPY那行的resource)必须是工作目录的相对路径;
所以,在img目录外面这样build也是一样的:
docker build -t my/base img/
-t 指定镜像在仓库的名字;
-f 指定dockfile,因为我们这里用的默认名称Dockerfile,所以不用指定;
--network=host build也是启动了一个镜像执行的,因为默认的bridge网络模式有网络损耗,所以如果build中包含较多外网访问,建议改为host:
docker build --network=host -t my/base .
下面启动测试下这个镜像:
# docker run --name mb -dti my/base c86b648c10174271e080f90e8d437a4ee2e25993003bdc68317477514349cb10 # docker attach mb [root@c86b648c1017 /]# which java /usr/local/jdk1.7.0_65/jre/bin/java [root@c86b648c1017 /]# java -version java version "1.7.0_65" Java(TM) SE Runtime Environment (build 1.7.0_65-b17) Java HotSpot(TM) 64-Bit Server VM (build 24.65-b04, mixed mode)