Dockerfile实现
1)Dockerfile 概述
- 我们目前都是手动拉取镜像,手动进行配置,手动安装依赖,手动编译安装,创建用户……这个过程类似于命令行使用ansible模块(繁琐,不方便重复执行)
- 书写Dockerfile把之前手动创建自定义镜像的过程,通过Dockerfile里面的指令实现,类似于书写playbook
- Dockfile用于根据要求自动创建镜像
2)Dockerfile 构建过程
过程
- 编写Dockerfile 文件
- dockerbuild构建镜像
- docker run 运行容器
- docker push 上传镜像
须知
- 每个保留关键字指令都是大写字母
- 执行顺序是从上往下
- 表示注释
- 每一个指令都会提交一个新的镜像层
3) Dockerfile 的指令
FROM # 基础镜像,一切从这里开始构建
MAINTAINER # 镜像是哪位写的 姓名+邮箱
RUN # 镜像构建的时候需要运行的命令
ADD # copy内容到容器(压缩包,自动解压)
COPY # 类似ADD 将文件copy到容器中
WORKDIR # 指定镜像工作目录
VOLUME # 设置容器卷
EXPOSE # 指定暴露端口
CMD # 指定这个容器启动的时候要运行的命令(只有最后一个会生效,可被代替)
ENTRYPOINT # 指定这个容器启动的时候要运行的命令(可以追加命令)
ONBUILD # 当构一个被继承的容器dockerfile这个时候会运行ONBUILD 的指令触发指定。
ENV # 构建时设置环境变量
-
构建centos7–nginx:
-
:Dockerfile 使用
FROM centos:centos7.9.2009
MAINTAINER "This is quyi by Dockerfile"
RUN yum install -y wget curl
RUN cd /etc/yum.repos.d/\
&& wget https://mirrors.aliyun.com/repo/Centos-7.repo\
&& wget http://mirrors.aliyun.com/repo/epel-7.repo
RUN yum install -y nginx
RUN rm -rf /usr/share/nginx/html/index.html\
&& echo 'qy.nbrhce.com' > /usr/share/nginx/html/index.html
CMD ["nginx","-g","daemon off;"]
4) Dockerfile中的指令
- 都是大写
Dockerfile指令 | 含义 | 应用 | 建议 |
---|---|---|---|
Dockerfile开头部分 | |||
FROM |
指定基本镜像类似于docker pull 下载镜像 |
FROM ubuntu:20.04 | 尽量少写ubuntu或ubuntu:latest尽量指定具体的版本 |
LABEL |
用于指定容器的属性信息,作者个人联系方式(邮件) | LABEL maintainer=”quyi996 [email protected]” | 推荐使用LABEL,不推荐使用下面的MAINTAINER |
MAINTAINER | 不在使用,推荐使用LABEL 个人信息 | ||
ENV | 用于创建Dockerfile中使用的变量 | ENV Tengine_Version空格2.3.3 | 软件版本可以创建使用变量 |
Dockerfile中间处理部分 | |||
RUN |
制作镜像过程中需要的执行命令,通常系统配置服务配置,部署但不能出现阻塞当前终端的命令 | RUN系统命令即可 | 不建议使用连续多个RUN,合并连续多个RUN |
ADD |
可以把指定文件或目录拷贝到容器中(指定目录)压缩包解压,相当于当前目录 | ADD restart.tar.gz 空格 /app/code/restart | 拷贝压缩包使用 |
COPY |
可以把指定文件或目录拷贝到容器中(指定目录),不支持自动解压,相对于当前目录 | COPY nginx.conf 空格 /etc/nginx/nginx.conf | 拷贝文件或目录 |
WORKDIR | 指定容器的默认工作目录 | WORKDIR /app/code/restart ADD restart.tar.gz 空 |
一般用于配合ADD,COPY需要书写容器中路径指令,Dockerfile中使用相对路径操作容器 |
VOLUME | 挂载数据卷 | VOLUME /usr/share/nginx/html | 创建随机数据卷挂载容器的目录,未来推荐docker run 的时候指定 -v 即可 |
Dockerfile结尾部分书写的内容 | |||
EXPOSE |
指定镜像要对外暴露的端口 | EXPOSE 80 | 用于指定一个或多个容器的端口,未来这个端口可以被IP识别 |
CMD |
用于指定容器的入口命令,入口命令可以在docker run的时候替换,运行后 | CMD ["命令","参数 01","参数02"] CMD ["nginx","- g","daemon off;"] | 大部分都会使用CMD |
ENTRYPOINT | 用于指定容器的入口命令,无法被docker run 替换,docker run指定的时候仅仅作为entrypoint命令的参数而已 | ENTRYPOINT ["executable", "param1", "param2"] | 使用不多 |
5)案例01 编译安装tengine变成Dockerfile
- Docker书写流程-对照上面案例手动搭建的
FROM centos:centos7.9.2009
LABEL maintainer="This is quyi by Dockerfile"
RUN yum install -y wget\
&& cd /etc/yum.repos.d/\
&& wget https://mirrors.aliyun.com/repo/Centos-7.repo\
&& wget http://mirrors.aliyun.com/repo/epel-7.repo
RUN cd /tmp\
&& wget http://tengine.taobao.org/download/tengine-2.3.3.tar.gz\
&& tar xf tengine-2.3.3.tar.gz\
&& cd tengine-2.3.3\
&& yum install -y make gcc zlib-devel pcre-devel openssl-devel\
&& ./configure --prefix=/app/tools/\
--user=nginx\
--group=nginx\
--with-http_ssl_module\
--with-http_v2_module\
--with-http_realip_module\
--with-http_stub_status_module\
--with-http_mp4_module\
--with-stream \
--with-stream_ssl_module\
--with-stream_realip_module\
--add-module=modules/ngx_http_upstream_check_module/\
--add-module=modules/ngx_http_upstream_session_sticky_module\
&& make\
&& make install\
&& ln -s /app/tools/sbin/nginx /sbin\
&& groupadd nginx\
&& useradd -g nginx nginx\
&& echo 'qy.nbrhce.com' > /app/tools/html/index.html
EXPOSE 80
CMD ["nginx","-g","daemon off;"]
#构建成功
Successfully built b7226374548a
Successfully tagged new-quyi-tengine:latest
#启动
[root@docker02 /server/tools/file]# docker run -itd --name quyi-tengine-v1 -p 80:80 new-quyi-tengine:latest
06) CMD与ENTRYPOINT的区别
区别 | CMD | ENTRYPOINT |
---|---|---|
共同点 | 用于设置容器入口命令,容器启动后默认运行什么指令什么参数 | 用于设置容器入口命令,容器启动后默认运行什么指令什么参数 |
共同点 | CMD [“命令”,“参数”,“参数2”] | ENTRYPOINT [“命令”,“参数1”,“参数2”] |
区别(不是同步使用) | 用户通过docker run /exec 启动进入容器的时候,指定了命令,这个命令会替代CMD命令和参数 | 用户通过docker run /exec 启动进入容器的时候,指定了命令,指定的命令,选项会成为ENTRYPOINT命令的选项 |
区别(同步使用) | CMD写的入口命令和命令的选项(可以被替换) | 入口的指令不可替换,一般指定脚本,脚本用于判断用户docker run/exec 的时候是否输入了命令, 如果没加 docker run -d nginx:1.20.2 ,这种的就直接运行CMD如果加了,则运行对应的命令和选项 |
- 案例理解:CMD或ENTRYPONT的时候
- CMD
#Dockerfile
FROM ubuntu:20.04
RUN touch oldboy.txt
CMD ["top","-b","-c"]
#测试
[root@docker02 /docker-v2]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1f5df3a23cd3 test_cmd "top -b -c" 40 seconds ago Up 40 seconds try-1
[root@docker02 /docker-v2]# docker run -d --name try-2 test_cmd sleep 90
[root@docker02 /docker-v2]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1ffca110063d test_cmd "sleep 90" 3 seconds ago Up 2 seconds try-2
#总结:如果在Dockerfile中CMD中写入了命令,在docker run 后面加参数就会执行命令行上的参数
- ENTRYPOINT
#用户通过docker run/exec 启动进入容器的时候,指定了命令指定的命令,选项会成为ENTRYPOINT命令的选项
docker run -d --name "test_entrypoint" test:ubunt_entrypoint
docker run -d --name "test_entrypoint_sLeep9" test:ubunt_entrypoint sleep 9
- CMD 与 ENTRYPOINT
#一起用
FROM ubuntu:20.04
RUN touch oldboy.txt
ENTRYPOINT ["top"]
CMD ["-b","-c"]
[root@docker02 /docker-v2]# docker run -it --name 'bbb' aaa
#这样写就是整合一起就是个命令 默认的 命令行不需要加等参数
#如果后面加参数就会报错
07)多阶段提交
- 在1个dockerfile中使用多个FROM,以减小最终镜像大小
- tengine+restart项目多阶段提交
- 1️⃣创建镜像的时候起个别名FROM xxx AS temp
- 2️⃣对中间镜像进行操作,下载依赖,下载软件包,编译
- 3️⃣创建镜像 FROM ubuntu:20.04
- 4️⃣把中间镜像的命令,配置文件/目录复制到最终镜像中,复制代码
- 5️⃣EXPOSE 80 , 设置入口指令CMD
FROM ubuntu:20.04 AS demo
LABEL auther=quyi sys_version=ubuntu_20.04
RUN sed -ri 's#archive.ubuntu.com|security.ubuntu.com#mirrors.aliyun.com#g' /etc/apt/sources.list\
&& apt update\
&& apt install -y wget libssl-dev make gcc pcre2-utils libpcre3-dev zlib1g-dev
RUN cd /tmp/\
&& wget http://tengine.taobao.org/download/tengine-2.3.3.tar.gz\
&& tar xf tengine-2.3.3.tar.gz\
&& cd tengine-2.3.3\
&& ./configure --prefix=/app/tools/tengine-2.3.3\
--user=nginx\
--group=nginx\
--with-http_ssl_module\
--with-http_v2_module\
--with-http_realip_module\
--with-http_stub_status_module\
--with-http_mp4_module\
--with-stream\
--with-stream_ssl_module\
--with-stream_realip_module\
--add-module=modules/ngx_http_upstream_check_module/\
--add-module=modules/ngx_http_upstream_session_sticky_module\
&& make\
&& make install
FROM ubuntu:20.04
COPY --from=demo /app/ /app/
RUN sed -ri 's#archive.ubuntu.com|security.ubuntu.com#mirrors.aliyun.com#g' /etc/apt/sources.list\
&& apt update\
&& apt install -y libssl-dev pcre2-utils libpcre3-dev zlib1g-dev\
&& ln -s /app/tools/tengine-2.3.3/sbin/nginx /sbin/ \
&& groupadd nginx\
&& useradd -g nginx nginx\
&& rm -rf /app/tools/tengine-2.3.3/html/*\
&& rm -rf /tmp/*\
&& rm -rf /var/cache/*
ADD restart.tar.gz /app/tools/tengine-2.3.3/html/
EXPOSE 80 443
CMD ["nginx","-g","daemon off;"]
[root@docker01 /docker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu-tengine seo 267c26d252c2 About a minute ago 194MB
nginx latest 605c77e624dd 4 months ago 141MB
ubuntu 20.04 ba6acccedd29 7 months ago 72.8MB
centos centos7.9.2009 eeb6ee3f44bd 8 months ago 204MB
#构建与运行
[root@docker01 /docker]# docker rm -f ubuntn-tengine
ubuntn-tengine
[root@docker01 /docker]# docker run -itd --name ubuntn-tengine -p 80:80 ubuntu-tengine:seo
- 应用场景:
- 适用于构建场合,先通过中间镜像进行编译,编程结果存放到新的镜像中
- FROM ubuntu:20.04 AS demo
- FROM ubuntu:20.04
- ADD –from
- COPY –from=demo …
08)Dockfile--php自定义镜像插件
主要是针对php连接web服务时候,缺少插件连接不上导致,
以下是自定义插件--用户是nginx带ID
FROM php:7.4.29-fpm-alpine
LABEL Description='Extension gd mysqli pdo-mysql redis' Author='quyi'
ENV URL https://pecl.php.net/get/redis-5.3.7.tgz
ENV DIR /usr/src/php/ext/
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apk/repositories \
&& apk add zlib-dev libpng-dev libwebp-dev libjpeg-turbo-dev freetype-dev \
&& docker-php-source extract \
&& wget -P /tmp ${URL} \
&& tar xf /tmp/redis-5.3.7.tgz -C ${DIR}/ \
&& mv ${DIR}/redis-5.3.7 ${DIR}/redis \
&& cd ${DIR}/gd \
&& docker-php-ext-configure gd \
--enable-gd \
--with-webp \
--with-jpeg \
--with-freetype \
&& docker-php-ext-install gd \
&& cd ${DIR} \
&& docker-php-ext-install mysqli \
&& docker-php-ext-install pdo_mysql \
&& docker-php-ext-install redis \
&& addgroup -g 101 nginx \
&& adduser -s /sbin/nologin -D -S -H -u 101 -G nginx nginx \
&& sed -i 's#www-data#nginx#g' /usr/local/etc/php-fpm.d/www.conf \
&& rm -fr /var/cache/* /tmp/* /usr/src/php
EXPOSE 9000
CMD ["php-fpm"]