- A+
Dockerfile
基本结构
Dockerfile 是一个文本格式的配置文件,用户可以使用 Dockerfile 快速创建自定义镜像。
Dockerfile 由一行行命令语句组成,并且支持以 # 开头的注释行。
Docker分为四部分:
基础镜像信息
维护者信息
镜像操作指令
容器启动时默认要执行的指令
例如:
# 第一行必须指定基于的基础镜像 FROM centos # 维护者信息 LABEL MANTAINER "lvnanhai66 1@36.com" # 镜像操作指令 RUN useradd -r -M -s /sbin/nologin apache # 容器启动时默认要执行的指令 CMD ["/usr/local/apache/bin/httpd","-D","FOREGROUND"]
其中,一开始必须指明所基于的镜像名称,接下来一般会说明维护者信息。
后面则是镜像操作指令,例如RUN指令,RUN指令将对镜像执行跟随的命令。每运行一条RUN指令,镜像添加新的一层,并提交。
最后是CMD指令来指定运行容器时的操作指令。
指令
指令的一般格式为INSTRUCTION arguments,指令包括:
FROM
LABEL MAINTAINER
RUN
CMD
EXPOSE
ENV
ADD
COPY
ENTRYPOINT
VOLUME
USER
WORKDIR
ONBUILD
FROM
功能为指定基础镜像,并且必须是第一条指令。
如果不以任何镜像为基础,那么写法为:FROM scratch。
同时意味着接下来所写的指令将作为镜像的第一层开始
FROM centos //基于centos的镜像 语法: FROM <image> FROM <image>:<tag> FROM <image>:<digest> 三种选项,其中<tag>和<digest>是可选项,如果没有选择那么默认就是latest
LABEL MAINTAINER
指定维护者信息
语法:LABEL MAINTAINER <name email_address> LABEL MANTAINER "lvnanhai66 1@36.com"
RUN
功能为运行指定的命令
RUN命令有两种格式
1.RUN command
2.RUN ["executable", "param1", "param2"]
前者将在shell终端中运行命令,即/bin/sh -c;后者则使用exec执行。指定使用其他终端可以通过第二种方式实现,例如:RUN ["/bin/bash","-c","echo hello"]
每条RUN指令将在当前镜像基础上执行指定命令,并提交为新的镜像。当命令较长时可以使用 来换行
[root@localhost ~]# cd httpd/ [root@localhost httpd]# ls Dockerfile files [root@localhost httpd]# vim Dockerfile [root@localhost httpd]# cat Dockerfile FROM busybox LABEL MANTAINER "lvnanhai66 1@36.com" RUN echo "hello lnh" > /tmp/abc [root@localhost httpd]# podman build -t httpd:1.0 . STEP 1/3: FROM busybox STEP 2/3: LABEL MANTAINER "lvnanhai66 1@36.com" --> d761206551e STEP 3/3: RUN echo "hello lnh" > /tmp/abc COMMIT httpd:1.0 --> 80125d342c8 Successfully tagged localhost/httpd:1.0 80125d342c8d86708b7c9a572ea46876a361a2c6a6b21c6b4ad66c4c00dd0b37 [root@localhost httpd]# podman run -it --rm httpd:1.0 /bin/sh / # cd /tmp/ /tmp # ls abc
CMD
CMD支持三种格式:
1.CMD ["executable","param1","param2"]使用exec执行,推荐方式
2.CMD command param1 param2在/bin/sh中执行,提供给需要交互的应用
3.CMD ["param1","param2"]提供给ENTRYPOINT的默认参数
CMD用于指定启动容器时默认要执行的命令,每个Dockerfile只能有一条CMD命令。如果指定了多条命令,只有最后一条会被执行。
如果用户启动容器时指定了运行的命令,则会覆盖掉CMD指定的命令。
不要把RUN和CMD搞混了。
RUN是构件容器时就运行的命令以及提交运行结果
CMD是容器启动时执行的命令,在构件时并不运行,构件时紧紧指定了这个命令到底是个什么样子
CMD ["/usr/local/apache/bin/httpd","-D","FOREGROUND"]
EXPOSE
格式为EXPOSE port [port...]。
例如:
EXPOSE 22 80 8443
EXPOSE用于告诉Docker服务器容器暴露的端口号,供互联系统使用。
在启动容器时通过-P,Docker主机会自动分配一个端口转发到指定的端口;
使用-p则可以具体指定哪个本地端口映射过来。
ENV
格式为ENV key value 。指定一个环境变量,会被后续RUN指令使用,并在容器运行时保持。
ENV PATH /usr/local/apache/bin:$PATH //配置环境变量
ADD
格式为ADD src dest
该命令将复制指定的src到容器中的dest。其中src可以是Dockerfile所在目录的一个相对路径(文件或目录);也可以是一个URL;还可以是一个tar文件(会自动解压为目录)。
[root@localhost httpd]# ls Dockerfile files [root@localhost httpd]# ls files/ apr-1.7.0.tar.gz apr-util-1.6.1.tar.gz entrypoint.sh httpd-2.4.54.tar.gz [root@localhost httpd]# vim Dockerfile [root@localhost httpd]# cat Dockerfile FROM busybox ADD files/apr-1.7.0.tar.gz /tmp/ [root@localhost httpd]# podman build -t httpd:2.0 . STEP 1/2: FROM busybox STEP 2/2: ADD files/apr-1.7.0.tar.gz /tmp/ COMMIT httpd:2.0 --> 5a9f6d599dc Successfully tagged localhost/httpd:2.0 5a9f6d599dc3245e3bfba5877bd84f155d9410e1fff6a679a8ebab954f530f1a [root@localhost httpd]# podman run -it --rm httpd:2.0 /bin/sh / # cd tmp/ /tmp # ls apr-1.7.0 /tmp #
COPY
格式为COPY <src> <dest>。 复制本地主机的<src>(为Dockerfile所在目录的相对路径,文件或目录)为容器中的<dest>。目标路径不存在时会自动创建。 当使用本地目录为源目录时,推荐使用COPY。
ENTRYPOINT
ENTRYPOINT有两种格式:
ENTRYPOINT ["executable","param1","param2"]
ENTRYPOINT command param1 param2(在shell中执行)
配置容器启动后执行的命令,并且不可被docker run提供的参数覆盖。而且,如果在docker run的后面提供了参数,这些命令行参数会被当作参数传递给ENTRYPOINT指定的程序。
每个Dockerfile中只能有一个ENTRYPOINT,当指定多个ENTRYPOINT时,只有最后一个生效。
例如:ENTRYPOINT ["/bin/bash","/entrypoint.sh"]
VOLUME
格式为VOLUME ["/data"]。
创建一个可以从本地主机或其他容器挂载的挂载点,一般用来存放数据库和需要保持的数据等
USER
格式为USER daemon。
指定运行容器时的用户名或UID,后续的RUN也会使用指定用户。
当服务不需要管理员权限时,可以通过该命令指定运行用户。并且可以在之前创建所需要的用户,例如:
RUN groupadd -r postgres && useradd -r -g postgres postgres
要临时获取管理员权限可以使用gosu,而不推荐sudo。如果不指定,容器默认是root运行。
WORKDIR
语法:
WORKDIR /path/to/workdir
设置工作目录,对RUN,CMD,ENTRYPOINT,COPY,ADD生效。如果不存在则会创建,也可以设置多次。
如:
WORKDIR /a WORKDIR b WORKDIR c RUN pwd
pwd执行的结果是/a/b/c
WORKDIR也可以解析环境变量
如:
ENV DIRPATH /path WORKDIR $DIRPATH/$DIRNAME RUN pwd
pwd的执行结果是/path/$DIRNAME
ONBUILD
格式为ONBUILD [INSTRUCTION]。
配置当所创建的镜像作为其他镜像的基础镜像时,所执行的操作指令。
例如,Dockerfile使用如下的内容创建了镜像image-A
[...] ONBUILD ADD . /app/src ONBUILD RUN /usr/local/bin/python-build --dir /app/src [...]
此时,如果基于image-A创建新的镜像时,新的Dockerfile中使用FROM image-A指定基础镜像时,会自动执行ONBUILD指令的内容,等价于在后面添加了两条指令。
FROM image-A # Automatically run the following ADD . /app/src RUN /usr/local/bin/python-build --dir /app/src
使用ONBUILD指令的镜像,推荐在标签中注明,例如ruby:1.9-onbuild。
创建镜像
用podman进行dockefile做一个httpd编译安装的镜像,要求要控制版本号,要用到dockerfile中大部分指令及用脚本方式启动程序,上传到官方镜像仓库
[root@localhost ~]# mkdir httpd [root@localhost ~]# cd httpd/ [root@localhost httpd]# touch Dockerfile [root@localhost httpd]# mkdir files [root@localhost httpd]# ls Dockerfile files //创建一个目录,在这个目录下面创建一个Dockerfile文件和存放安装包的目录files [root@localhost httpd]# cd files/ [root@localhost files]# wget https://downloads.apache.org/apr/apr-1.7.0.tar.gz https://downloads.apache.org/apr/apr-util-1.6.1.tar.gz https://downloads.apache.org/httpd/httpd-2.4.54.tar.gz [root@localhost files]# ls apr-1.7.0.tar.gz apr-util-1.6.1.tar.gz httpd-2.4.54.tar.gz //下载安装包 [root@localhost files]# vim entrypoint.sh [root@localhost files]# cat entrypoint.sh #!/bin/bash sed -i '/^#ServerName/s/#//g' /usr/local/apache/conf/httpd.conf exec "$@" [root@localhost files]# chmod +x entrypoint.sh //赋予脚本执行权限 [root@localhost files]# ll total 11136 -rw-r--r--. 1 root root 1093896 Apr 5 2019 apr-1.7.0.tar.gz -rw-r--r--. 1 root root 554301 Oct 23 2017 apr-util-1.6.1.tar.gz -rwxr-xr-x. 1 root root 88 Aug 30 16:43 entrypoint.sh -rw-r--r--. 1 root root 9743277 Jun 8 16:42 httpd-2.4.54.tar.gz //写一个脚本作为启动程序 [root@localhost files]# cd .. [root@localhost httpd]# ls Dockerfile files [root@localhost httpd]# vim Dockerfile [root@localhost httpd]# cat Dockerfile FROM centos LABEL MANTAINER "lvnanhai66 1@36.com" ENV apache_version 2.4.54 //apache版本号 ENV PATH /usr/local/apache/bin:$PATH //配置环境变量 ADD files/apr-1.7.0.tar.gz /usr/src/ ADD files/apr-util-1.6.1.tar.gz /usr/src/ ADD files/httpd-${apache_version}.tar.gz /usr/src/ //这样可以更换 ADD files/entrypoint.sh / //将这个脚本放到根下面 RUN useradd -r -M -s /sbin/nologin apache && cd /etc/yum.repos.d && rm -r * && curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-vault-8.5.2111.repo && sed -i -e '/mirrors.cloud.aliyuncs.com/d' -e '/mirrors.aliyuncs.com/d' /etc/yum.repos.d/CentOS-Base.repo && yum clean all && yum makecache && yum -y install gcc gcc-c++ make openssl-devel pcre-devel expat-devel libtool && cd /usr/src/apr-1.7.0 && sed -i '/$RM "$cfgfile"/d' configure && ./configure --prefix=/usr/local/apr && make && make install && cd ../apr-util-1.6.1 && ./configure --prefix=/usr/local/apr-util --with-apr=/usr/local/apr && make && make install && cd ../httpd-${apache_version} && ./configure --prefix=/usr/local/apache --enable-so --enable-ssl --enable-cgi --enable-rewrite --with-zlib --with-pcre --with-apr=/usr/local/apr --with-apr-util=/usr/local/apr-util/ --enable-modules=most --enable-mpms-shared=all --with-mpm=prefork && make && make install && yum clean all && //清除缓存 yum -y remove gcc gcc-c++ make && //这些编译工具可以清除 rm -rf /tmp/* /usr/src/* //这个下面的文件可以清除 EXPOSE 80 //映射的端口号 WORKDIR /usr/local/apache //相当于cd这个目录 CMD ["/usr/local/apache/bin/httpd","-D","FOREGROUND"] //此处加了绝对路径 ENTRYPOINT ["/bin/bash","/entrypoint.sh"] //不知道有没有权限,可以直接加bin/bash [root@localhost httpd]# podman build -t httpd:v3.0 . .... STEP 13/13: ENTRYPOINT ["/bin/bash","/entrypoint.sh"] COMMIT httpd:v3.0 --> f65d0bb9ee1 Successfully tagged localhost/httpd:v3.0 f65d0bb9ee17efdffdb53dc52fb92188aaa5fa1ea90cc11e2939855ba71f8ec3 让这个镜像运行一个容器进行测试: [root@localhost httpd]# podman images REPOSITORY TAG IMAGE ID CREATED SIZE localhost/httpd v3.0 f65d0bb9ee17 About a minute ago 405 MB docker.io/library/httpd latest dabbfbe0c57b 8 months ago 148 MB quay.io/centos/centos latest 300e315adb2f 21 months ago 217 MB [root@localhost httpd]# podman run -d httpd:v3.0 fcf786713d9b55793b997cc98e3571535b1fd4c0553409f3bb18bfd9d51fd234 [root@localhost httpd]# podman ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES fcf786713d9b localhost/httpd:v3.0 /usr/local/apache... 4 seconds ago Up 4 seconds ago xenodochial_morse [root@localhost httpd]# podman inspect -l |grep -i ipaddr //过滤查看ip "IPAddress": "10.88.0.6", "IPAddress": "10.88.0.6", [root@localhost httpd]# curl 10.88.0.6 //访问成功 <html><body><h1>It works!</h1></body></html> 上传镜像: [root@localhost httpd]# podman tag httpd:v3.0 docker.io/lvnanhai66/httpd:v3.0 [root@localhost httpd]# podman images REPOSITORY TAG IMAGE ID CREATED SIZE localhost/httpd v3.0 f65d0bb9ee17 8 minutes ago 405 MB docker.io/lvnanhai66/httpd v3.0 f65d0bb9ee17 8 minutes ago 405 MB docker.io/library/httpd latest dabbfbe0c57b 8 months ago 148 MB quay.io/centos/centos latest 300e315adb2f 21 months ago 217 MB [root@localhost httpd]# podman login docker.io Username: lvnanhai66 Password: Login Succeeded! [root@localhost httpd]# podman push docker.io/lvnanhai66/httpd:v3.0 Getting image source signatures Copying blob 3f49a2cae693 done Copying blob 90fc92241475 done Copying blob 8cfba8022d3f done Copying blob 34214738da46 done Copying blob bea1ef732da4 done Copying blob 2653d992f4ef done Copying config f65d0bb9ee done Writing manifest to image destination Storing signatures
拉取自己的镜像运行容器: [root@localhost ~]# podman run -d --name web -P docker.io/lvnanhai66/httpd:v3.0 Trying to pull docker.io/lvnanhai66/httpd:v3.0... Getting image source signatures Copying blob 929704506730 skipped: already exists Copying blob 26ad906b0de6 done Copying blob c63ffcca07e0 done Copying blob 45fdf32689c6 done Copying blob 0b040dd24d11 done Copying blob 841f6f1ffedd done Copying config f65d0bb9ee done Writing manifest to image destination Storing signatures 4d770508e2552c6ab554079fccf9e72ed79ed43ffcad5d6564d2cac3a07527d6 [root@localhost ~]# podman ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 4d770508e255 docker.io/lvnanhai66/httpd:v3.0 /usr/local/apache... 8 seconds ago Up 8 seconds ago 0.0.0.0:40607->80/tcp web [root@localhost ~]# podman ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 4d770508e255 docker.io/lvnanhai66/httpd:v3.0 /usr/local/apache... 19 seconds ago Up 19 seconds ago 0.0.0.0:40607->80/tcp web //如果发现拉取不下来可以加加速器进行注释(cd /etc/containers/然后vim registries.conf)