构建自己的image
构建自己的镜像,有两种方法:
Usage: docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
Create a new image from a container's changes
Options:
-a, --author string Author (e.g., "John Hannibal Smith <hannibal@a-team.com>")
-c, --change list Apply Dockerfile instruction to the created image (default [])
--help Print usage
-m, --message string Commit message
-p, --pause Pause container during commit (default true)
将现有的容器固化成镜像。
下面我们创建一个可以ssh的镜像:
1.启动一个容器:
$ docker run -i -t ubuntu:16.04 /bin/bash
2.启动成功后,登录容器,执行所需要的操作:
root@4aa51652291a:/# apt-get update
root@4aa51652291a:/# apt-get install openssh-server
# mkdir /var/run/sshd #不创建该目录,ssh的时候会报错
passwd #输入用户密码,我这里设置为123456,便于SSH客户端登陆使用
# vi /etc/ssh/sshd_config
更改为:PermitRootLogin yes #允许客户端通过root用户ssh
service ssh restart
exit #退出容器
3.保存镜像
$ docker commit 4aa51652291a ubuntusshd
5f5a2a905d89fa2daf3b9537fa0cf5e0c83ad0e95d6078420d2a582080120418
4.以后台方式运行容器
$ docker run -d -p 50022:22 ubuntusshd /usr/sbin/sshd –D
ubuntu容器内运行着的SSH Server占用22端口,对外为50022端口。
5.查看容器是否运行
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
61bb4b7d981f ubuntusshd:v2 "/usr/sbin/sshd -D" 4 minutes ago Up 4 minutes 0.0.0.0:50022->22/tcp sad_pasteur
6.客户端连接
ssh root@127.0.0.1 -p 50022
使用docker commit来扩展一个image比较简单,但它不容易在一个团队中分享它。我们使用docker build 来创建一个新的image。为此,我们需要创建一个dockerfile,包含一些如何创建我们的image的指令。
1.创建一个Dockerfile: $ vi Dockerfile 加入如下内容:
FROM ubuntu:14.04
MAINTAINER jim <jim@126.com>
RUN apt-get install haproxy
RUN apt-get install –y openssh-server
2.创建image
docker build -t="user1/web:v2" .
Sending build context to Docker daemon 2.048 kB
Sending build context to Docker daemon
Step 0 : FROM ubuntu:14.04
---> 07f8e8c5e660
Step 1 : MAINTAINER jim <jim@126.com>
---> Using cache
---> 857c5cf770aa
Step 2 : RUN apt-get install haproxy
---> Using cache
---> 3e333b27becb
Successfully built 3e333b27becb
3.查看是否存在该images
# docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
user1/web v2 3e333b27becb 3 hours ago 190 MB
格式为 FROM <image> 或 FROM <image>:<tag> 。
第一条指令必须为 FROM 指令。并且,如果在同一个Dockerfile中创建多个镜像时,可以使用多个 FROM指令(每个镜像一次)。
格式为 MAINTAINER <name> ,指定维护者信息。
格式为 RUN <command> 或 RUN ["executable", "param1", "param2"] 。
前者将在shell终端中运行命令,即 /bin/sh -c ;后者则使用 exec 执行。指定使用其它终端可以通过第二种方式实现,例如 RUN ["/bin/bash", "-c", "echo hello"] 。 每条 RUN 指令将在当前镜像基础上执行指定命令,并提交为新的镜像。当命令较长时可以使用 \ 来换行。
支持三种格式:
CMD ["executable","param1","param2"] 使用 exec 执行,推荐方式;
CMD command param1 param2 在 /bin/sh 中执行,提供给需要交互的应用;
CMD ["param1","param2"] 提供给 ENTRYPOINT 的默认参数;
指定启动容器时执行的命令,每个Dockerfile只能有一条 CMD 命令。如果指定了多条命令,只有最后一条会被执行。 如果用户启动容器时候指定了运行的命令,则会覆盖掉 CMD 指定的命令。
格式为 EXPOSE <port> [<port>...] 。
告诉Docker服务端容器暴露的端口号,供互联系统使用。
格式为 ENV <key> <value> 。
指定一个环境变量,会被后续 RUN 指令使用,并在容器运行时保持。 例如
ENV PG_MAJOR 9.3
ENV PG_VERSION 9.3.4
RUN curl -SL http://example.com/postgres-$PG_VERSION.tar.xz | tar -xJC /usr/src/postgress && …
ENV PATH /usr/local/postgres-$PG_MAJOR/bin:$PATH
格式为 ADD <src> <dest> 。
该命令将复制指定的到容器中的。 其中可以是Dockerfile所在目录的一个相对路径;也可以是一个URL;还可以是一个tar文件(自动解压为目录)。 如果源文件是个目录,则将该目录下的所有文件复制到,但不包括该目录。
格式为 COPY <src> <dest> 。
复制本地主机的(为Dockerfile所在目录的相对路径)到容器中的。 如果源文件是个目录,则将该目录下的所有文件复制到,但不包括该目录。 当使用本地目录为源目录时,推荐使用 COPY 。
两种格式:
ENTRYPOINT ["executable", "param1", "param2"]
ENTRYPOINT command param1 param2 (shell中执行).
配置容器启动后执行的命令,并且不可被 docker run 提供的参数覆盖。 每个Dockerfile中只能有一个 ENTRYPOINT ,当指定多个时,只有最后一个起效。
格式为 VOLUME ["/data"] 。
创建一个可以从本地主机或其他容器挂载的挂载点,一般用来存放数据库和需要保持的数据等。
格式为 USER daemon 。
指定运行容器时的用户名或UID,后续的 RUN 也会使用指定用户。 当服务不需要管理员权限时,可以通过该命令指定运行用户,并且可以在之前创建所需要的用户。 例如:
RUN groupadd -r postgres && useradd -r -g postgres postgres
要临时获取管理员权限可以使用 gosu ,而不推荐 sudo 。
格式为 WORKDIR /path/to/workdir 。
为后续的 RUN 、 CMD 、 ENTRYPOINT 指令配置工作目录。 可以使用多个 WORKDIR 指令,后续命令如果参数是相对路径,则会基于之前命令指定的路径。 例如:
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
则最终路径为 /a/b/c 。
格式为 ONBUILD [INSTRUCTION] 。
配置当所创建的镜像作为其它新创建镜像的基础镜像时,所执行的操作指令。 例如: Dockerfile使用如下的内容创建了镜像 image-A 。
[...]
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
[...]
如果基于A创建新的镜像时,新的Dockerfile中使用 FROM image-A 指定基础镜像时,会自动执行 ONBUILD 指令内容,等价于在后面添加了两条指令。
FROM image-A
#Automatically run the following
ADD . /app/src
RUN /usr/local/bin/python-build --dir /app/src
FROM ubuntu:16.04
MAINTAINER jim <jim@test.com>
COPY sources.list /etc/apt/sources.list
RUN rm -rf /bin/sh && ln -s /bin/bash /bin/sh && \
apt-get update && \
apt-get install build-essential python curl telnet -y && \
mkdir -p /data/soft
COPY heirloom-mailx_12.5.orig.tar.gz /data/soft
COPY smtp /data/soft
COPY meld3-1.0.2.tar.gz /data/soft
COPY setuptools-0.6c11.tar.gz /data/soft
COPY supervisor-3.3.1.tar.gz /data/soft
RUN cd /data/soft && cat smtp >> /etc/nail.rc && \
cd /data/soft && tar zxvf heirloom-mailx_12.5.orig.tar.gz && cd heirloom-mailx-12.5 && make && make install UCBINSTALL=/usr/bin/install && \
cd /data/soft && tar zxf setuptools-0.6c11.tar.gz && cd setuptools-0.6c11 && python setup.py build && python setup.py install && \
cd /data/soft && tar zxvf meld3-1.0.2.tar.gz && cd meld3-1.0.2 && python setup.py install && \
cd /data/soft && tar zxf supervisor-3.3.1.tar.gz && cd supervisor-3.3.1 && python setup.py install && \
mkdir -p /etc/supervisor/conf.d
COPY supervisord.conf /etc/supervisor/supervisord.conf
COPY curl.conf /etc/supervisor/conf.d/curl.conf
COPY detectport.conf /etc/supervisor/conf.d/detectport.conf
RUN apt-get autoremove && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
VOLUME ["/usr/local/share/detect"]
CMD ["/usr/local/bin/supervisord","-c","/etc/supervisor/supervisord.conf"]
为了减少镜像大小,Dockerfile需要遵循如下原则:
RUN apt-get autoremove && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
所需软件:
$ mkdir -p tomcat7/soft
将以上两个软件上传到soft目录,需要解压开的软件
编辑script文件,用于修改环境变量和tomcat启动脚本
$ vi soft/script
#!/bin/bash
#准备环境变量
echo -e 'JAVA_HOME=ROOT_DIR/JDK_DIR
PATH=$PATH:$JAVA_HOME/bin
CLASSPATH=.:$JAVA_HOME/lib:$JAVA_HOME/jre/lib
export JAVA_HOME PATHCLASSPATH' >> /etc/profile
#准备tomcat启动脚本
echo -e '#!/bin/bash
source /etc/profile
sh ROOT_DIR/TOMCAT_DIR/bin/catalina.sh run' > ${ROOT_DIR}/run.sh
#替换以上文件中为自定义的目录
sed -i "s#ROOT_DIR#${ROOT_DIR}#g" /etc/profile
sed -i "s#JDK_DIR#${JDK}#g" /etc/profile
sed -i "s#ROOT_DIR#${ROOT_DIR}#g" ${ROOT_DIR}/run.sh
sed -i "s#TOMCAT_DIR#${TOMCAT}#g" ${ROOT_DIR}/run.sh
$ vi Dockerfile
FROM ubuntu:16.04
MAINTAINER jim <jim@126.com>
ENV ROOT_DIR=/app
ENV TOMCAT=apache-tomcat-7.0.59
ENV JDK=jdk1.7.0_75
WORKDIR ${ROOT_DIR}
RUN rm -rf /bin/sh && ln -s /bin/bash /bin/sh && \
mkdir -p ${ROOT_DIR}
COPY soft ${ROOT_DIR}
RUN cd ${ROOT_DIR}/${TOMCAT}/bin && sed -i 's/\"&\"//g' catalina.sh && \
cd ${ROOT_DIR} && sh script
ENV LANG C.UTF-8
EXPOSE 8080 22
VOLUME ["${ROOT_DIR}/${TOMCAT}/webapps","${ROOT_DIR}/${TOMCAT}/logs"]
CMD ["sh","/app/run.sh"]
首次build会需要一些时间,要下载基础镜像ubuntu:16.04
$ cd tomcat7
$ docker build -t="tomcat7:v1.0" .
构建完成后400M左右
tomcat7镜像构建完成后,可以启动个容器:
docker run -d -it \
--name tomcat7 \
--hostname tomcat7 \
--restart=always \
-p 8080:8080 \
-v /etc/localtime:/etc/localtime:ro \
-v /data/tomcat7/webapps:/app/apache-tomcat-7.0.59/webapps \
-v /data/tomcat7/logs:/app/apache-tomcat-7.0.59/logs \
--log-opt max-size=20m --log-opt max-file=5 \
tomcat7:v1.0
本脚本于用于一键创建容器,更改相关变量后可多次使用.
#!/bin/bash
DOCKER=/usr/bin/docker
CONTAINER_NAME=tomcat7
CONTAINER_DIR=/data/containers
IMAGE_NAME=tomcat7:v1.0
OUT_PORT=18081
COMMAND=/app/run.sh
#获取容器、镜像
GET_CO(){
CO_EXIST=$(${DOCKER} ps -a|awk '{print $NF}'|grep ${CONTAINER_NAME})
}
GET_IM(){
IM_EXIST=$(${DOCKER} images|awk '{print $1":"$2}'|grep -w ${IMAGE_NAME})
}
#创建容器
CREATE_CONTAINER(){
docker run -d -it \
--name ${CONTAINER_NAME} \
--hostname ${CONTAINER_NAME} \
--restart=always \
-p ${OUT_PORT}:8080 \
-v ${CONTAINER_DIR}/${CONTAINER_NAME}/webapps:/app/apache-tomcat-7.0.59/webapps \
-v ${CONTAINER_DIR}/${CONTAINER_NAME}/logs:/app/apache-tomcat-7.0.59/logs \
-v /etc/localtime:/etc/localtime:ro \
--log-opt max-size=20m --log-opt max-file=5 \
${IMAGE_NAME} \
${COMMAND}
sleep 1
GET_CO
if [ -z ${CO_EXIST} ];then
echo "[-] ${CONTAINER_NAME} created failed."
else
echo "[+] ${CONTAINER_NAME} created Successful, publish port ${OUT_PORT}."
fi
}
#判断镜像是否存在
GET_IM
if [ -z ${IM_EXIST} ];then
echo "[-] ${IMAGE_NAME} is not exist."
exit 1
else
echo "[+] Create a container from image ${IMAGE_NAME}."
fi
sleep 1
#判断容器是否存在
GET_CO
if [ -z ${CO_EXIST} ];then
CREATE_CONTAINER
else
echo "[-] ${CONTAINER_NAME} is exist."
exit 1
fi
未完待续......