Docker Dockerfile
一、什么是 Dockerfile
比如我想制作一个镜像,这个镜像安装了 lnmp 、redis 、elk 等各种软件,制作流程会是这样:
① 先下载一个基础镜像,如 centos
② 使用这个镜像启动成一个容器
③ 在容器中安装 lnmp 、redis 、elk 等各种软件
④ 最后再把容器制作成一个镜像
什么是 Dockerfile:Dockerfile 相当于一个命令集 ( 命令的集合 ) 文件,我们可以把上面的步骤都写到这个文件,然后执行这个文件就能生成一个镜像
二、Dockerfile 常用指令
FROM # 指定基于哪个镜像,语法:FROM <image> 或 FROM <image>:<tag>,如 FROM centos:latest MAINTAINER # 指定Dockerfile文件的作者信息,语法:MAINTAINER <name> <mail>,如 MAINTAINER xiaoming xiaoming@qq.com
LABEL # 用于定义镜像的 meta data(元数据),以描述该镜像的详细信息,以便他人下载时知道该镜像的情况,如 LABEL version="1.0" RUN # 指定要操作的命令,语法:RUN <command>,如 RUN yum install -y redis,也可以写成 RUN ["yum", "install", "-y", "redis"]
# 另外,我们每写一条RUN语句,就会在 docker history <image> 中多显示一层,因此尽量用 && 或 \ 把多条命令写成一条命令 CMD # 指定容器启动时要执行的命令,语法:CMD <command>,如 CMD yum install redis,如果命令有选项必须写成 CMD ["yum", "install", "-y", "redis"] EXPOSE # 指定容器要开放的端口,以便外部能访问,如 EXPOSE 22 80 443 表示开放 22 80 443 这三个端口,但必须结合 docker -p 80:80 这种形式来使用 ENV # 用于定义环境变量,如 ENV PATH /usr/local/bin:$PATH,也可以自定义用户变量,如 EVN MySQL_Version 5.6,定义的变量可以让 RUN 或 CMD 使用 ADD # 用于拷贝宿主机的文件到容器的某个目录里,语法:ADD <src> <dest>,如 ADD 1.txt /data 表示拷贝宿主机的1.txt到容器的/data目录,<src>也可以是一个url COPY # 用法与ADD一致,不同的是,ADD可以使用url,COPY不能使用url ENTRYPOINT # 指定容器启动时要执行的命令,用法与CMD一致,不同的是,CMD的命令会被覆盖,比如 docker run -itd centos bash 去启动容器时,bash就是启动容器时执行的命令 # 而如果我们写了 CMD echo 123 是不会执行的,因为被bash命令覆盖了,而我们使用ENTRYPOINT就不会被覆盖,而且会优先执行ENTRYPOINT指定的命令再执行bash命令 # 另外一点,如果我们再Dockerfile文件中写了多条CMD指令,那么只有最后一条会执行,使用ENTRYPOINT则每一条都会执行 VOLUME # 指定挂载目录,如 VOLUME ["/data"] 表示把宿主机的/data目录挂载到容器里,但不会指定挂载到容器里的哪个目录,需要使用 docker inspect 来查看,参考链接 USER # 指定启动容器的用户,如 USER root 表示使用 root 用户来启动容器 WORKDIR # 指定工作目录,对 RUN,CMD,ENTRYPOINT,COPY,ADD 生效,比如 WORKDIR /data,那么我执行 RUN echo 123 相当于执行 cd /data; echo 123
# 尽量使用 WORKDIR 而不要使用 RUN cd,因为如果目录不存在,WORKDIR会自动创建该目录,而 RUN cd 我们并不知道该目录是否存在
三、Dockerfile 实例:使用 Dockerfile 制作一个安装了 Nginx 的镜像
[root@localhost ~]$ vim Dockerfile # 注意文件名固定为Dockerfile FROM centos # 基于centos镜像,会自动去 Docker Hub 拉取 MAINTAINER panzekai 1210640219@qq.com # 指定该文件的作者信息 RUN yum install -y pcre-devel wget net-tools gcc zlib zlib-devel make openssl-devel # 安装一些依赖包 ADD http://nginx.org/download/nginx-1.12.2.tar.gz . # 下载nginx,默认的当前目录是根目录 RUN tar zxvf nginx-1.12.2.tar.gz # 解压nginx RUN mkdir -p /usr/local/nginx # 创建安装目录 RUN cd nginx-1.12.2 && ./configure --prefix=/usr/local/nginx && make && make install # 编译安装 RUN rm -fv /usr/local/nginx/conf/nginx.conf # 删除源配置文件 ADD http://www.apelearn.com/study_v2/.nginx_conf /usr/local/nginx/conf/nginx.conf # 下载新的配置文件 EXPOSE 80 # 开放80端口 ENTRYPOINT /usr/local/nginx/sbin/nginx && tail -f /etc/passwd # 启动容器时启动nginx,,加上 tail -f /etc/passwd 是为了让容器一直
# 运行,否则执行完启动nginx容器就直接停止运行了,这是Dockerfile的一个Bug
[root@localhost ~]$ docker build -t centos_with_nginx . # 运行Dockerfile文件,"-t"用于指定产生的镜像名,"."表示在哪个路径下寻找Dockerfile文件
[root@localhost ~]$ docker images # 查看是否生成了镜像 REPOSITORY TAG IMAGE ID CREATED SIZE centos_with_nginx latest 6365087f4297 54 seconds ago 346MB
[root@localhost ~]$ docker run -itd -p 80:80 centos_with_nginx # 使用镜像运行容器,并把宿主机端口映射到容器 [root@localhost ~]$ docker exec -it 336bb211d1 bash # 进入容器 [root@336bb211d1f6 /]# ps aux | grep nginx # 查看是否运行了nginx root 1 0.1 0.0 11680 1356 pts/0 Ss+ 23:22 0:00 /bin/sh -c /usr/local/nginx/sbin/nginx && tail -f /etc/passwd root 7 0.0 0.0 20540 620 ? Ss 23:22 0:00 nginx: master process /usr/local/nginx/sbin/nginx nobody 9 0.0 0.1 22984 3204 ? S 23:22 0:00 nginx: worker process nobody 10 0.0 0.1 22984 3204 ? S 23:22 0:00 nginx: worker process root 25 0.0 0.0 9088 668 pts/1 S+ 23:22 0:00 grep --color=auto nginx
[root@localhost ~]$ curl 127.0.0.1:80 # 在宿主机访问一下,看看是否成功 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> ......
可以参考一下官方安装 Nginx 的 Dockerfile:https://github.com/docker-library/nginx/blob/master/1.7/Dockerfile