Dockerfile
是为了快速构建镜像
Dockerfile
由一行行命令语句组成,并且支持以#开头的注释行。
一般而言,Dockerfile
分为4个部分:
基础镜像信息<br/>维护者信息<br/>镜像操作指令<br/>容器启动时执行指令
Dockerfile指令:
(1)FROM
指定所创建镜像的基础镜像,如果本地不存在,则默认会去Docker Hub下载指定镜像。
格式:FROM <image>或 FROM <image>:<tag>
任何Dockerfile中的第一条指令必须为FROM指令。并且在同一个Dockerfile中创建多个镜像时,可以使用多个FROM指令(每个镜像一次)
(2)MAINTAINER
格式:MAINTAINER <name>,指定维护者信息
该信息会写入生成镜像的Author属性域中
(3)RUN
运行指定命令。
格式:RUN <command>或RUN ["executable","param1","param2"]。注意,后一个指令会被解析为Json数组,因此必须用双引号。
前者默认将在shell终端运行命令,即/bin/sh -c;后者则使用exec执行,不会启动shell环境。
比如:RUN yum install httpd
RUN ["/bin/bash","-c","echo hello"]
每条RUN指令将在当前镜像基础上执行指定命令,并提交为新镜像。当命令过长时,可以使用\来换行。
(4)CMD
CMD指令用来指定启动容器时默认执行的命令。
支持3种格式:
•CMD ["executable", "param1", "param2"]<br/>•CMD command param1 param2<br/>•CMD ["param1", "param2"]
RUN和CMD看起来很像,但是CMD用来指定容器启动时用到的命令,只能有一条。如果指定了多条命令,只有最后一条会被执行。如果用户启动容器时,指定了运行命令,则会覆盖掉CMD指定的命令。
比如:CMD ["/bin/bash", "/usr/local/nginx/sbin/nginx", "-c", "/usr/local/nginx/conf/nginx.conf"]
(5)EXPOSE
声明镜像内服务所监听的端口
格式:EXPOSE <port> [<port>...]
比如:EXPOSE 22 80 443
告诉Docker服务端容器暴露的端口号,供互联系统使用。在启动容器时需要通过-P,Docker主机会自动分配一个端口转发到指定端口;使用-p,则可以具体指定哪个本地端口映射过来。
(6)ENV
格式:ENV <key> <value>或ENV <key>=<value>,指定一个环境变量,会被后续RUN指令使用,在镜像启动的容器中也会存在。
比如:ENV PATH /usr/local/mysql/bin:$PATH
(7)ADD
格式:ADD <src> <dest>
将本地的一个文件或目录拷贝到容器的某个目录里。其中<src>为Dockerfile所在目录的相对路径,它也可以是一个URL;如果为tar文件,会自动解压到<dest>路径下。<dest>可以是镜像内的绝对路径,或者相对于工作目录(WORKDIR)的相对路径。
• ADD <conf/vhosts> </usr/local/nginx/conf>
(8)COPY
格式:COPY <src> <dest>
复制本地主机的<src>(为Dockerfile所在目录的相对路径,文件或目录)为容器中的<dest>。目录路径不存在时,会自动创建。当使用本地目录为源目录时,推荐使用COPY。
(9)ENTRYPOINT
指定镜像的默认入口命令,该入口命令在启动容器时作为根命令执行,所有传入值作为该命令的参数
两种格式:
ENTRYPOINT ["executable", "param1", "param2"] (exec调用执行)<br/>ENTRYPOINT command param1 param2 (shell中执行)
此时,CMD指令指定值将作为根命令的参数
配置容器启动后执行的命令,并且不可被docker run 提供的参数覆盖,每个Dockerfile中只能有一个ENTRYPOINT,当指定多个ENTRYPOINT时,只有最后一个生效。
在运行时,可以被--entrypoint参数覆盖掉,如docker run --entrypoint
•我们在Dockerfile中指定如下CMD:
• CMD ["/bin/echo", "test"]
• 启动容器的命令是 docker run aming这样会输出test
• 假如启动容器的命令是 docker run -it aming /bin/bash 什么都不会输出
• ENTRYPOINT不会被覆盖,而且会比CMD或者docker run指定的命令要靠前执行
• ENTRYPOINT ["echo", "test"]
• docker run -it aming 123
• 则会输出 test 123,这相当于要执行命令 echo test 123
(10)VOLUME
创建一个数据卷挂载点
格式:VOLUME ["/data"]
创建一个可以从本地主机或其他容器挂载的挂载点,一般用于存放数据库和需要保持的数据等。
(11)USER
格式:USER daemon
指定运行容器时的用户名或UID,后续的RUN也会指定用户。
当服务不需要管理员权限时,可以通过该指令指定运行的用户。并且可以在之前创建所需要的用户。例如:
RUN groupadd -r postgres && useradd -r -g postgres postgres。要临时获取管理员权限可以使用gosu,而不推荐sudo
(12)WORKDIR
格式:WORKDIR /path/to/workdir
为后续的RUN,CMD,ENTRYPOINT指令配置工作目录。可以使用多个WORKDIR指令,后续命令如果参数是相对路径,则会基于之前命令指定的路径。例如:
WORKDIR /a<br/>WORKDIR b<br/>WORKDIR c<br/>RUN pwd
则最终路径为:/a/b/c
(13)ARG
指定一些镜像内使用的参数(例如版本号信息等),这些参数在执行docker build命令时,才以--build-arg<varname>=<value>格式传入
格式:ARG<name>[=<default value>]
则可以用docker build --build-arg<name>=<value>.来指定参数值
(14)ONBUILD
配置当所创建的镜像作为其他镜像的基础镜像时,所执行的创建操作指令。
格式:ONBUILD [INSTRUCTION]
例如,Dockerfile使用如下的内容创建了镜像image-A:
[...]<br/>ONBUILD ADD . /app/src<br/>ONBUILD RUN /usr/local/bin/python-build --dir /app/src<br/>[...]
如果基于image-A创建新的镜像时,新的Dockerfile中使用FROM image-A指定基础镜像,会自动执行ONBUILD指令的内容
(15)STOPSIGNAL
指定所创建镜像启动的容器接收退出的信号值。例如:
STOPSIGNAL signal
(16)HEALTHCHECK
配置所启动容器如何进行健康检查(如何判断健康与否),自docker 1.12开始支持
格式有两种:
HEALTHCHECK [OPTIONS] CMD command:根据所执行命令返回值是否为0来判断;
HEALTHCHECK NONE:禁止基础镜像中的健康检查。
OPTION支持:
①--interval=DURATION(默认为:30s):过多久检查一次;
②--timeout=DURATION(默认为:30s):每次检查等待结果的超时;
③--retries=N(默认为:3):如果失败了,重试几次才最终确定失败。
(17)SHELL
指定其他命令使用shell时的默认shell类型
SHELL ["executable","parameters"]
默认值为["/bin/sh","-c"]
build镜像
Usage: docker build [OPTIONS] PATH | URL | -[flags]Options:
-t, --tag list # 镜像名称
-f, --file string # 指定Dockerfile文件位置
# docker build .
# docker build -t shykes/myapp .
# docker build -t shykes/myapp -f /path/Dockerfile /path
# docker build -t shykes/myapp http://www.example.com/Dockerfile
构建php基础镜像
[root@localhost php]# vim Dockerfile-php
FROM centos:7
MAINTAINER dev.ceba.com
RUN yum install epel-release -y && \
yum install -y gcc gcc-c++ make gd-devel libxml2-devel \
libcurl-devel libjpeg-devel libpng-devel openssl-devel \
libmcrypt-devel libxslt-devel libtidy-devel autoconf \
iproute net-tools telnet wget curl && \
yum clean all && \
rm -rf /var/cache/yum/*
RUN wget http://docs.php.net/distributions/php-5.6.36.tar.gz && \
tar zxf php-5.6.36.tar.gz && \
cd php-5.6.36 && \
./configure --prefix=/usr/local/php \
--with-config-file-path=/usr/local/php/etc \
--enable-fpm --enable-opcache \
--with-mysql --with-mysqli --with-pdo-mysql \
--with-openssl --with-zlib --with-curl --with-gd \
--with-jpeg-dir --with-png-dir --with-freetype-dir \
--enable-mbstring --with-mcrypt --enable-hash && \
make -j 4 && make install && \
cp php.ini-production /usr/local/php/etc/php.ini && \
cp sapi/fpm/php-fpm.conf /usr/local/php/etc/php-fpm.conf && \
sed -i "90a \daemonize = no" /usr/local/php/etc/php-fpm.conf && \
mkdir /usr/local/php/log && \
cd / && rm -rf php* && \
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
ENV PATH $PATH:/usr/local/php/sbin
COPY php.ini /usr/local/php/etc/
COPY php-fpm.conf /usr/local/php/etc/
WORKDIR /usr/local/php
EXPOSE 9000
CMD ["php-fpm"]
构建nginx基础镜像
[root@localhost nginx]# vim Dockerfile-nginx
FROM centos:7
MAINTAINER dev.cabe.com
RUN yum install -y gcc gcc-c++ make \
openssl-devel pcre-devel gd-devel \
iproute net-tools telnet wget curl && \
yum clean all && \
rm -rf /var/cache/yum/*
RUN wget http://nginx.org/download/nginx-1.15.5.tar.gz && \
tar zxf nginx-1.15.5.tar.gz && \
cd nginx-1.15.5 && \
./configure --prefix=/usr/local/nginx \
--with-http_ssl_module \
--with-http_stub_status_module && \
make -j 2 && make install && \
rm -rf /usr/local/nginx/html/* && \
echo "ok" >> /usr/local/nginx/html/status.html && \
cd / && rm -rf nginx-1.15.5* && \
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
ENV PATH $PATH:/usr/local/nginx/sbin
#COPY nginx.conf /usr/local/nginx/conf/nginx.conf
WORKDIR /usr/local/nginx
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
部署lnmp网站平台
1、自定义网络
[root@localhost nginx]# docker network create lnmp
b445b2fd52081134427849986ca3db98b5e888185f51018d0dbea58eaf5bc6e2
2、创建Mysql容器
[root@localhost nginx]# docker run -d \
--name lnmp_mysql \
--net lnmp \
--mount src=mysql-vol,dst=/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 -e MYSQL_DATABASE=wordpress mysql:5.7 --character-set-server=utf8
3、创建PHP容器
[root@localhost nginx]# docker run -d --name lnmp_php --net lnmp --mount src=wwwroot,dst=/wwwroot php:v1
4、创建Nginx容器
[root@localhost nginx]# docker run -d --name lnmp_nginx --net lnmp -p 80:80 \
--mount type=bind,src=$(pwd)/nginx.conf,dst=/usr/local/nginx/conf/nginx.conf --mount src=wwwroot,dst=/wwwroot nginx:v1
[root@localhost nginx]# docker volume ls
DRIVER VOLUME NAME
local mysql-vol
local wwwroot
浏览器访问
部署wordpress博客为例 https://cn.wordpress.org/wordpress-4.9.4-zh_CN.tar.gz
[root@localhost ~]# wget https://cn.wordpress.org/wordpress-4.9.4-zh_CN.tar.gz
[root@localhost ~]# tar xf wordpress-4.9.4-zh_CN.tar.gz
[root@localhost ~]# mv wordpress /var/lib/docker/volumes/wwwroot/_data/
配置连接数据库
部署成功
构建tomcat基础镜像
[root@localhost tomcat]# vim Dockerfile-tomcat
FROM centos:7
MAINTAINER dev.ceba.com
ENV VERSION=8.0.53
RUN yum install java-1.8.0-openjdk wget curl unzip iproute net-tools -y && \
yum clean all && \
rm -rf /var/cache/yum/*
#RUN wget http://192.168.31.211/apache-tomcat-${VERSION}.tar.gz && \
RUN wget http://mirrors.shu.edu.cn/apache/tomcat/tomcat-8/v${VERSION}/bin/apache-tomcat-${VERSION}.tar.gz && \
tar zxf apache-tomcat-${VERSION}.tar.gz && \
mv apache-tomcat-${VERSION} /usr/local/tomcat && \
rm -rf apache-tomcat-${VERSION}.tar.gz /usr/local/tomcat/webapps/* && \
mkdir /usr/local/tomcat/webapps/test && \
echo "ok" > /usr/local/tomcat/webapps/test/status.html && \
sed -i '1a JAVA_OPTS="-Djava.security.egd=file:/dev/./urandom"' /usr/local/tomcat/bin/catalina.sh && \
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
ENV PATH $PATH:/usr/local/tomcat/bin
WORKDIR /usr/local/tomcat
EXPOSE 8080
CMD ["catalina.sh", "run"]
[root@localhost tomcat]# docker build -t tomcat:v1 -f Dockerfile-tomcat .
基于构建的镜像启动容器
[root@localhost tomcat]# docker run -d --name=tomcat_web tomcat:v1
e60b29a7a9b1433a85ee9bd0b4eb258bd84fa5bfa88780bf947d4a65f711e1fb
[root@localhost tomcat]# docker exec tomcat_web ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
67: eth0@if68: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
[root@localhost tomcat]# curl 172.17.0.2:8080/test/status.html
ok
构建项目
[root@localhost tomcat]# vim Dockerfile-tomcat-project
FROM tomcat:v1
COPY jenkins.war /usr/local/tomcat/webapps/ROOT.war
访问项目