Dockerfile构建企业级镜像
在服务器上可以通过源码或rpm方式部署Nginx服务,但不利于大规模的部署。为提高效率,可以通过Dockerfile的方式将Nginx服务封装到镜像中,然后Docker基于镜像快速启动容器,实现服务的快速部署。
Dockerfile是一个用来构建镜像的文本文件,文本内容包含一条条构建镜像所需的指令和说明。
Dockerfile构建
Dockerfile用于定义Docker镜像构建过程的文件。是一个文本文件,包含一系列的指令和参数,用于自动化构建Docker镜像。Dockerfile中每个指令代表一个构建步骤,可以指定所使用的基础镜像、安装软件、配置环境变量、复制文件、运行命令等。
- 构建镜像
在Dockerfile文件所在目录下执行命令
docker build -t image_name:tag .# 例子
docker build -t myapp:1.0 .
-t
指定镜像名称和标签 .
表示是Dockerfile文件的所在目录
- 运行容器
docker run -d -p 8080:80 myapp:1.0
Dockerfile文件内容语法
FROM
:指定所用的基础镜像,如FROM centos:latest
FROM centos
RUN yum install -y httpd
COPY index.html /var/www/html/
EXPOSE 80
CMD ["httpd","-DFOREGROUND"]
该Dockerfile创建一个基于CentOS的镜像,安装httpd服务器,将index.html文件复制到/var/www/html/
目录下,将容器的80端口暴露,最后容器启动时启动httpd服务器
MAINTAINER
:指定镜像维护者的信息,MAINTAINER yourname <email>
RUN
:在容器中执行的命令,如RUN apt-get update && apt-get install -y curl
RUN用于在镜像构建过程中的执行命令。在Dockerfile中,每一个RUN指令都会在一个新的镜像层上执行,最终形成一个新的镜像。
RUN命令中可以执行任何有效的Linux命令,如安装软件包、创建文件夹、运行脚本等。
RUN指令有两种模式:shell模式和exec模式。shell模式下,命令在容器默认的shell中运行,在exec模式下,命令以exec系统调用的方式运行。exec模式更加高效和安全
exec模式示例
FROM alpine
RUN apk add --no-cache git
RUN --mount=type=cache,target=/root/.cache \git clone https://github.com/example/example.git
WORKDIR /example
RUN --mount=type=cache,target=/root/.cache \apk add --no-cache python3 \&& pip3 install -r requirements.txt
CMD ["python3", "app.py"]
使用exec模式,第一个RUN命令,使用apk安装git,第二个和第三个RUN指令中,使用–mount选项指定缓存目录,安装Python3和Python依赖库。第二个RUN指令中,使用Git克隆了一个仓库目录。最后在CMD中执行了python的程序。
CMD
:容器启动时执行的命令
CMD命令可以有多个,但是只有最后一个会被执行。
同样有shell模式和exec模式,exec模式更安全和高效。要注意的是:使用exec模式时,必须将CMD指令和参数放入JSON数组中。否则Docker会将整个字符串当成命令执行,可能导致错误。
ENTRYPOINT
: 指令用于设置容器启动时默认命令或应用程序,与CMD指令类似,都是容器启动时执行的命令。但当ENTRYPOINT
和CMD
同时出现时,CMD
指令的作用就是为ENTRYPOINT
命令指定的程序或命令提供默认参数。也就是说,CMD中定义的参数将会把ENTRYPOINT中的参数给覆盖。
FROM ubuntu:latest
RUN apt-get update && apt-get install -y curl
ENTRYPOINT ["curl","-s","-o","/dev/null"]
CMD ["https://www.google.com"]
最后的效果就是使用curl
指令获取Google网站的内容…,达到了参数拼接的效果。
EXPOSE
:声明容器运行监听的端口,EXPOSE 80
声明容器监听的网络端口。此指令不会在容器启动时自动将端口映射到宿主机上,而是提供给运行容器的人员一个提示,告诉他们应该监听的 端口。
FROM nginx
EXPOSE 80
启动容器时,使用-p
参数指定宿主机和容器的端口映射配置。
docker run -d -p 8080:80 my-nginx-image
宿主机监听8080端口,转发到容器的80端口上。
ENV
: 设置环境变量,ENV_MYSQL_ROOT_PASSWORD=123456
FROM ubuntu:latest
ENV MY_NAME="Docker"
CMD echo "Hello, ${MY_NAME}!"
输出Hello, Docker
但是需要注意的:Docker中ENV的变量只能是容器内部使用,只有像CMD
,ENTRYPOINT
这样的命令来使用,像RUN
等构建镜像时的命令是使用不了的,可以用ARG声明的环境变量。
ARG
:设置环境变量或传递Docker镜像构建时参数,可以动态进行传值
# 定义一个构建参数,可以设置默认值,若无指定参数的值,采用默认值
ARG <name>[=<default value>]# 实例
ARG BUILD_VERSION
ARG COMMIT_SHA
Dockerfile中使用
ARG VERSION=latest
FROM ubuntu:${VERSION}
构建镜像时可以动态传值,若无值则使用默认值
docker build --build-arg VERSION=1.0.0 -t myimage
ADD
: 将本地文件或目录复制到容器中,若本地是一个压缩包,先把压缩包解压后放入容器ADD ./app /app
# 语法
ADD <源路径> <目标路径># 示例
ADD example.tar.gz /app/ # ADD命令自动解压
ADD https://example.com/file.tar.gz /app/ # 可以从URL下载文件到容器中
注意:ADD命令会修改文件的权限和属主信息,若不需要ADD高级功能尽量采用COPY
COPY
: 复制本地文件或目录到容器中,是压缩包时不会解压
需要注意:
源路径必须在构建上下文中存在(放到和Dockerfile文件统一目录),否则Docker构建过程会失败
# 语法
COPY <源路径> <目标路径># 示例:将宿主机本目录下的app目录,复制到容器中的app目录下
COPY ./app/ /app
WORKDIR
: 设置工作目录WORKDIR /app
,类似于linux的cd
命令VOLUME
: 设置持久化数据的挂载点VOLUME /data
Docker中创建一个挂载点,实现数据持久化功能。使用VOLUME指令创建的挂载点会在容器启动时自动创建,且容器销毁时挂载点不会被删除,数据可以长久保存。
VOLUME指令不会在主机上创建一个新目录,而是将一个已经存在的目录挂载到容器中。因此在使用VOLUME指令时,需要在容器创建时通过-v
或--mount
参数指定挂载目录。
VOLUME /data
启动容器时
docker run -v /path/to/data:/data <image>
将主机的/path/to/data
目录和容器的/data
目录进行挂载。若是未声明/path/to/data
的主机目录,那么会在主机随机生成一个目录(匿名数据卷
)和容器/data
目录进行挂载。
匿名数据卷在docker的存储目录是/var/lib/docker/volumes
中,匿名数据卷在容器被删除时,也会被清理掉,所以尽量采用命令数据卷方式,防止数据意外丢失。
案例:构建Nginx镜像
# 创建一个dockerfile的目录
mkdir nginxDockerfile# 进入目录
cd nginxDockerfile# 创建Dockerfile文件
vim Dockerfile
创建内容如下:
FROM centos # 使用centos作为基础镜像
MAINTAINER xiaolu # 作者WORKDIR /etc/yum.repos.d/ # 进入yum配置目录
RUN sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-* \ && sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-* # 设置os8的yum源
\&& yum makecache # 更新缓存\&& yum -y install nginx # 安装nginx
\&& yum -y install wget # 安装wget
COPY index.html /usr/share/nginx/html/ # 将文件拷贝到镜像
EXPOSE 80 # 提示暴露端口
ENTRYPOINT ["/usr/sbin/nginx","-g","daemon off;"] # 容器启动执行的命令
若是centos8镜像,记得给配置上yum源,同时最好可以一条RUN将他们全都执行完毕,因为每执行一个RUN,镜像就会增加一层。daemon off;
是nginx的全局配置参数,用于让Nginx在前台运行,不作为守护进程在后台运行。
Tips:Docker容器启动时,默认把容器内第一个进程,也就是pid=1的程序作为判断docker容器是否在运行的依据,若pid=1的程序崩溃,那么docker容器自动关闭。该例中,nginx若是后台运行,Docker未执行自定义的CMD前,Nginx的pid=1,运行完毕后Nginx变成后台进程,docker将判断nginx程序崩溃或结束,自动关闭docker容器。
记得Dockerfile文件中把中文注释删了哦,小心报错!!,完整版贴这里
FROM centos
MAINTAINER xiaolu
WORKDIR /etc/yum.repos.d/
RUN sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-* \&& sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-* \&& yum makecache \&& yum -y install wget \&& yum -y install nginx
COPY index.html /usr/share/nginx/html/
EXPOSE 80
ENTRYPOINT ["/usr/sbin/nginx","-g","daemon off;"]
- 创建页面
vim index.html
<html><head><title>page added to Dockerfile</title></head><body><h1>Hello,My Name is Xiaolu,Welcome to my nginx page!</h1></body>
</html>
- 构建镜像
docker build -t xiaolu/nginx:v1 .
- 查看镜像是否构建完毕
docker images |grep nginx
- 镜像构建完毕了,创建启动容器
docker run -d -p 80:80 --name html2 xiaolu/nginx:v1
访问我们的宿主机的80端口将会映射到容器的80端口,获取到我们需要的资源。
这里说个小知识点,当80:80
写成80
时,意思是随机分配宿主机的端口和容器80端口进行映射。