什么是Dockerfile?
Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。
使用Dockerfile定制镜像
仅讲解如何运行Dockerfile 文件来定制一个镜像
1、定制一个nginx镜像(构建好的镜像内会有一个/usr/share/nginx/html/index.html文件)
在一个空目录下,新建一个名为Dockerfile文件,并在文件内添加以下内容:
FROM nginx
RUN echo '这是一个本地构建的nginx镜像' > /usr/share/nginx/html/index.html
2、FROM和RUN指令作用
FROM:定制的镜像都是基于FROM的镜像,这里的nginx就是定制需要的基础镜像。后续的操作都是基于nginx。
RUN:用于执行后续跟着的命令行命令。有以下两种格式:
shell格式:
RUN <命令行命令>
# <命令行命令> 等同于,在终端操作的shell命令。
exec格式:
RUN ["可执行文件", "参数1", "参数2"]
# 例如:
# RUN ["./test.php", "dev", "offline"] 等价于 RUN ./test.php dev offline
注:Dockerfile 的指令每执行一次都会在docker上新建一层。所以过多无意义的层,会造成镜像膨胀过大,例如:
FROM centos // 基于哪个镜像
RUN yum -y install wget // 仅安装指定的软件命令
RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" // 去链接地址获取这个文件并且取名为redis.tar.gz
RUN tar -xvf redis.tar.gz
// 拓展点
(1)
yum 提供了查找、安装、删除某一个、一组甚至全部软件包的命令
yum语法
yum [options] [command] [package...]
option: 可选,选项包括-h(帮助),-y(当安装过程提示选择全部为"yes"), -q(不显示安装的过程)等等
command: 要进行的操作。
package: 安装的包名。
(2)
tar 备份文件
tar -zxvf用于解压.tar.gz后缀结尾的
tar -xvf用于解压.tar后缀结尾的
以上执行会创建3层镜像
FROM centos
RUN yum -y install wget \
&& wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"
&& tar -xvf redis.tar.gz
// && 符号连接命令,这样执行后,只会创建 1 层镜像。
开始构建镜像
在Dockerfile 文件的存放目录,执行构建动作
以下示例
FROM 基于哪个镜像;--- 指定构建新image时使用的基础image,通常必须Dockerfile的第一个有效指令,但其前面也可以出现ARG指令
MAINTAINER 注明作者;
COPY 复制宿主机文件进入镜像不会解压(只能用相对路径,不能用绝对路径);
ADD 复制宿主机文件进入镜像(假如文件时.tar.gz文件会解压)
WORKDIR 指定工作目录,假如路径不存在会创建路径
ENV 设置容器的环境变量(比较构造一个带jdk的centos镜像,那么就可以配置centos容器中的jdk环境变量)
EXPOSE 暴露容器端口(比如配置一个带tomcat的centos镜像,那么就可以通过这个命令讲tomcat的8080端口暴露出来)
RUN 在构建镜像的时候执行,作用于镜像层;
ENTRYPOINT 在容器启动的时候执行,作用于容器层,dockerfile里有多条时只允许执行最后一条
CMD 在容器启动的时候执行,作用于容器层,dockerfile里有多条时只允许执行最后一条,容器启动后执行默认的命令或参数,允许被修改。
命令格式(shell不允许携带cmd参数,exec允许携带cmd参数):
shell命令格式:RUN yum install -y net-tools
exec命令格式:RUN ["yum","install","-y","net-tools"]
// 1、FROM
// 指定基础镜像,必须为第一个命令
格式:
FROM <image>
FROM <image>:<tag>
FROM <image>@<digest>
示例:
FROM mysql:5.6
注:
tag或digest是可选的,如果不适用这两个值时,会使用latest版本的基础镜像
// 2、MAINTAINER(新版即将废弃)
// 维护者信息
格式:
MAINTAINER <name>
示例:
MAINTAINER bertwu
MAINTAINER xxx@163.com
MAINTAINER bertwu <xxx@163.com>
// 3、RUN
// 构建镜像时执行的命令
// RUN 用于在构建镜像时执行命令,其有以下两种命令执行方式:
shell 执行
格式:
RUN <command>
exec 执行
格式:
RUN ["executable", "param1", "param2"]
示例:
RUN ["executable", "param1", "param2"]
RUN apk update
RUN ["/etc/execfile", "arg1", "arg1"]
注:RUN指令创建的中间镜像会被缓存,并会在下次构建中使用。如果不想使用这些缓存镜像,可以在构建时指定--no-cache参数,如:docker build --no-cache
// 4、ADD
// 将本地文件添加到容器中,tar类型文件会自动解压(网络压缩资源不会被解压),可以访问网络资源,类似wget
格式:
ADD <src>...<dest>
ADD ["<src>", ..."<dest>"] // 用于支持包含空格的路径
示例:
ADD hom* /mydir/ # 添加所有以"hom"开头的文件
ADD hom?.txt /mydir/ # ?替换一个单字符,例如:"home.txt"
ADD test relativeDir/ # 添加"test"到指定工作目录`WORKDIR`/relativeDir/
ADD test /absoluteDir/ # 添加"test"到 /absoluteDir/
// 5、COPY
// 功能类似ADD ,但是是不会自动解压文件,也不能访问网络资源
// 6、CMD
// 构建镜像后调用,也就是在容器启动时才进行调用。
格式:
CMD ["executable", "param1", "param2"] (执行可执行文件,优先)
CMD ["param1", "param2"] (设置了ENTRYPOINT,则直接调用ENTRYPOINT添加参数)
CMD command param1 param2 (执行shell内部命令)
示例:
CMD echo 'This is a test." | wc -l
CMD ["/usr/bin/wc", "--help"]
// 注!!!:CMD不同于RUN,CMD用于指定在容器启动时所要执行的命令,而RUN用于指定镜像构建时索要执行的命令
// 7、ENTRYPOINT
// 配置容器,使其可执行化。配置CMD可省去"application", 只使用参数
格式:
ENTRYPOINT ["executable", "param1", "param2"] (可执行文件,优先)
ENTRYPOINT command param1 param2 (shell内部命令)
示例:
FROM ubuntu
ENTRYPOINT ["ls", "/usr/local"]
CMD ["/usr/local/tomcat"]
之后,docker run 传递的参数,都会先覆盖cmd,然后由cmd传递给entrypoint,做到灵活应用
// 注!!!: ENTRYPOINT与CMD非常类似,不同的是通过docker run 执行的命令不会覆盖ENTRYPOINT,而docker run 命令中指定的任何参数,都会被当作参数再次传递给CMD。Dockerfile中只允许有一个ENTRYPOINT命令,多指定时会覆盖前面的设置,而只执行最后的ENTRYPOINT指令。 通常情况下,ENTRYPOINT与CMD一起使用,ENTRYPOINT写默认命令,当需要参数时候使用CMD传参
// 8、LABEL
// 用于为镜像添加元数据
格式:
LABEL <key>=<value> <key>=<value> <key>=<value> ...
示例:
LABEL version="1.0" description="这是一个web服务器" by="IT笔录"
注:
使用LABEL指定元数据时,一条LABEL指定可以指定一或多条元数据,指定多条元数据时不同元数据,之间用空格分隔。推荐将所有元数据通过一条LABEL指令指定,以免生成过多的中间镜像。
// 9、ENV
// 设置环境变量
格式:
ENV <key> <value> # <key>之后的所有内容均会被视为其<value>的组成部分,因此一次只能设置一个变量
ENV <key>=<value> ... # 可以设置多个变量,每个变量为一个"<key>=<value>"的键值对,如果<key>中包含空格,可以使用\来进行转义,也可以通过""来进行标示;另外,反斜线也可以用于续行
示例:
ENV myName John Doe
ENV myDog Rex The Dog
ENV myCat=fluffy
// 10、EXPOSE
// 指定于外界交互的端口
格式:
EXPOSE <port> [<port>...]
示例:
EXPOSE 80 443
EXPOSE 8080
EXPOSE 11211/TCP 11211/udp
注: EXPOSE并不会让容器的端口访问到主机。要使其可访问,需要在docker run运行容器时通过-p来发布这些端口,或通过-P参数来发布EXPOSE导出的所有端口。如果没有暴露端口,后期也可以通过-P 8080:80 方式映射端口,但是不能通过 -P 形式映射。
// 11、WORKDIR
// 工作目录,类似于cd命令
格式:
WORKDIR /path/to/wordir
示例:
WORKDIR /a (这时工作目录为/a)
WORKDIR b (这时工作目录为/a/b)
WORKDIR c (这时工作目录为/a/b/c)
注:
通过WORKDIR设置工作目录后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT、ADD、COPY等命令都会在该目录下执行。在使用docker run运行容器时,可以通过-w参数覆盖构建时所设置的工作目录。
// 12、USER
// 指定运行容器时的用户名或UID,后续的RUN也会使用指定用户。使用USER指定用户时,可以使用用户名、UID或GID,或是两者的组合。当服务不需要管理员权限时,可以通过该命令指定运行用户。并且可以在之前创建所需要的用户
格式:
USER user
USER user: group
USER uid
USER uid: gid
USER user: gid
USER uid: group
示例:
USER www
注:
使用USER指定用户后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT都将使用该用户。
镜像构建完成后,通过docker run运行容器时,可以通过-u参数来覆盖所指定的用户。
// 13、ARG
// 用于指定传递给构建运行时的变量(给dockerfile传参),相当于构建镜像时可以在外部为里面参数
格式:
ARG <name>[=<default value>]
示例:
ARG site
ARG build_user=www
// 14、ONBUILD
// 用于设置镜像触发器
格式:
ONBUILD [INSTRUCTION]
示例:
ONBUILD ADD ./app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
注:
当当前的镜像被用作其它镜像的基础镜像,该镜像中的触发器将被触发
制作镜像
- 如果有多个RUN,自上而下依次运行,每次运行都会形成新的层,建议&&放入一行运行
- 如果有多个CMD,只有最后一个运行
- 如果有多个ENTRYPOINT,只有最后一个运行
- 如果CMD和ENTRYPOINT共存,只有ENTRYPOINT运行,且最后的CMD会当作ENTRYPOINT的参数
镜像制作分两个阶段
1、docker build 阶段 基于dockerfile制作镜像(RUN,用于此阶段的运行命令)
2、docker run 阶段 基于镜像运行容器(CMD,基于image run容器时,需要运行的命令)
3、docker build 基于第一阶段的镜像被别人from制作新镜像(ENTRYPOINT或onbuild基于镜像重新构建新镜像时候在次阶段运行的命令)
源码编译制作nginx镜像
# Base images 基础镜像
FROM centos
# MAINTAINER 维护者信息
MAINTAINER bertwu
# ENV 设置环境变量
ENV PATH /usr/local/nginx/sbin:$PATH
# ADD 文件放在当前目录下,拷过去会自动解压
ADD nginx-1.8.0.tar.gz /usr/local/
ADD epel-release-latest-7.noarch.rpm /usr/local/
# RUN 执行以下命令
RUN rpm -ivh /usr/local/epel-release-latest-7.noarch.rpm
RUN yum install -y wget lftp gcc gcc-c++ make openssl-devel pcre-devel pcre && yum clean all
RUN useradd -s /sbin/nologin -M www
# WORKDIR x
实战
FROM docker.com/cv/node.14.0.3 //基于哪个镜像
EXPOSE 80
WORKDIR /code //指定工作目录,假如路径不存在会创建路径
COPY . /code //将当前文件拷贝到code(注空格)
RUN rm -rf build // 执行删除build
RUN yarn install // 安装node_modules
RUN yarn run build //打包(注这边指令名要跟package.json中得打包指令一样,如果npm run prod得话这边写成yarn run prod)
RUN mv dist /usr/share/nginx/html/poc //执行将dist文件夹移动到/usr/share/nginx/html/poc (注意这边要加上/poc跟运维沟通得path一致,然后前端项目中也要看情况而定有时publicPath也要写成/poc)
(关于健康检查healthz如果把他移动到public下健康检查就可以不用写,如果在Dockerfile文件同级就要写将健康检查移动到nginx中RUN mv healthz /usr/share/nginx/html //healthz跟dockerfile平级得情况)
RUN rm -rf /code // 删除code目录下所有文件:-rf加了就删除这个目录下得所有文件夹包括这个文件夹
CMD ["nginx", "-g", "daemon off;"] // 执行可执行得文件
// RUN:执行
// COPY:拷贝
// WORKDIR:创建目录
// rm:删除
// mv:移动
// -rf:下所有文件夹
sudo su // 普通用户切换管理员用户
docker ps |grey (llm-chat-web) // 查看指定服务名状态
docker exec -it (d5e3d71) bash //退出指定进程号的服务
cd (/user/share/ngix/html/) // 打开指定路径
ls //查看该路径下有哪些文件
docker ps // 查看所有内容
docker ps |grey // 查看指定内容
vim (Dockerfile) // 打开dockerfile文件
mkdir (/lyhtml) // 新建lythml文件夹
mv dist /lyhtml // 将dist移动到/lyhtml
创建code文件夹,拷贝当前文件至code文件夹,删除code文件夹下所有内容并删除code文件
新建code文件夹
将当前文件复制cp到code文件夹下
-r 若给出的源文件是一个目录文件,此时将复制该目录下所有的子目录和文件。
使用rm命令删除文件夹
使用 rm 命令删除文件夹的时候,一定要记得加上 -r 或 -R 选项,否则会报错。该选项表示递归删除文件夹,可以将该文件夹下的文件全部删除。加上 -f 选项将强制删除而不给任何提示。
// 先清空文件夹
cd code
rm -rf *
// 再使用rmdir命令删除该文件夹
cd ..
rmdir code
例子文章来源:https://www.toymoban.com/news/detail-458151.html
FROM nginx:stable-alpine
USER root
RUN apk update && apk add curl tzdata && \
cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
echo "Asia/Shanghai" > /etc/timezone
COPY nginx.conf /etc/nginx/nginx.conf
COPY healthz /usr/share/nginx/html
COPY dist /usr/share/nginx/html/wl-avatar-setting
EXPOSE 80
FROM daocloud.io/nginx
USER root
#修改时区
RUN rm -rf /etc/localtime && ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
COPY nginx.conf /etc/nginx/nginx.conf
COPY /dist /usr/share/nginx/html
EXPOSE 80
FROM nginx
# 将dist文件中的内容复制到 /usr/share/nginx/html/ 这个目录下面
COPY dist/ /usr/share/nginx/html/dist/
# 用本地的 nginx.conf 配置来替换nginx镜像里的默认配置
COPY nginx.conf /etc/nginx/nginx.conf
nginx.conf文章来源地址https://www.toymoban.com/news/detail-458151.html
#user nobody;
worker_processes auto;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
gzip on;
server {
listen 80;
server_name localhost;
charset utf-8;
location / {
root html;
try_files $uri $uri/ @router;
index index.html index.htm;
}
location @router {
rewrite ^.*$ /index.html break;
}
location /backendd/{
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 20M;
proxy_send_timeout 500;
proxy_read_timeout 480;
proxy_pass http://localhost:8992;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
events {
worker_connections 1024;
}
# softhar-h5 .................. start#
http {
include mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /etc/nginx/access.log main;
sendfile on;
server {
listen 80;
server_name beta.123.com;
location /softhar-h5{
alias /usr/share/nginx/html;
index index.html index.htm;
}
location /softhar-h5/api/v2/webhook{
proxy_http_version 1.1;
rewrite ^/softhar-h5/api/(.*)$ /$1 break;
# 使用的是beta环境的 内网网关地址
proxy_pass http://cloud.svc.clr.local:8080/;
}
location /softhar-h5/api/api{
proxy_http_version 1.1;
rewrite ^/softhar-h5/api/(.*)$ /$1 break;
proxy_pass http://api.ai/;
}
location /softhar-h5/payment{
alias /usr/share/nginx/html;
index index.html index.htm;
}
location /softhar-h5/payment/api/api2{
proxy_http_version 1.1;
rewrite ^/softhar-h5/payment/api/(.*)$ /$1 break;
proxy_pass http://apis.di.ai/;
}
}
# 正式环境start #
server {
listen 80;
server_name 123.com;
location /softhar-h5{
alias /usr/share/nginx/html;
index index.html index.htm;
}
location /softhar-h5/api/api{
proxy_http_version 1.1;
rewrite ^/softhar-h5/api/(.*)$ /$1 break;
proxy_pass http://api.ai/;
}
location /softhar-h5/payment{
alias /usr/share/nginx/html;
index index.html index.htm;
}
location /softhar-h5/payment/api/api2{
proxy_http_version 1.1;
rewrite ^/softhar-h5/payment/api/(.*)$ /$1 break;
proxy_pass http://apis.di.ai/;
}
}
# 正式环境end #
}
# softhar-h5 .................. end#
到了这里,关于Docker Dockerfile的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!