Dockerfile使用

Dockerfile使用

$ docker build . -t ImageName:ImageTag -f Dockerfile

Dockerfile是一堆指令,在docker build的时候,按照该指令进行操作,最终生成我们期望的镜像

FROM 指定基础镜像,必须为第一个命令

格式:
    FROM <image>
    FROM <image>:<tag>
示例:
    FROM mysql:5.7
注意:
    tag是可选的,如果不使用tag时,会使用latest版本的基础镜像

MAINTAINER 镜像维护者的信息

格式:
    MAINTAINER <name>
示例:
    MAINTAINER Yongxin Li
    MAINTAINER inspur_lyx@hotmail.com
    MAINTAINER Yongxin Li <inspur_lyx@hotmail.com>

实操:

[root@k8s-slave1 my-ubuntu-image]# vim Dockerfile 

# 告诉docker使用哪个基础镜像作为模板,后续命令都以这个镜像>

为基础 
FROM ubuntu
##添加
MAINTAINER Yongxin Li

# RUN命令会在上面指定的镜像里执行命令 

RUN apt-get update && apt install -y nginx

#告诉docker,启动容器时执行如下命令
CMD ["/usr/sbin/nginx", "-g","daemon off;"]

#构建镜像
#这里可以不加-f Dockerfile
[root@k8s-slave1 my-ubuntu-image]# docker build . -t test-maintainer 

#查看镜像详细信息,可以看到MAINTAINER镜像维护者信息
[root@k8s-slave1 my-ubuntu-image]# docker inspect test-maintainer 
......
"DockerVersion": "20.10.12",
        "Author": "Yongxin Li",
        "Config": {
            "Hostname": "",
            "Domainname": "",
            "User": "",
......

COPY|ADD 添加本地文件到镜像中

格式:
    COPY <src>... <dest>
示例:
    ADD hom* /mydir/          # 添加所有以"hom"开头的文件
    ADD test relativeDir/     # 添加 "test" 到 `WORKDIR`/relativeDir/
    ADD test /absoluteDir/    # 添加 "test" 到 /absoluteDir/

WORKDIR 工作目录(进入容器后默认的目录)

格式:
    WORKDIR /path/to/workdir
示例:
    WORKDIR /a  (这时工作目录为/a)
注意:
    通过WORKDIR设置工作目录后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT、ADD、COPY等命令都会在该
目录下执行

实操一:

[root@k8s-slave1 my-ubuntu-image]# vim Dockerfile 

# 告诉docker使用哪个基础镜像作为模板,后续命令都以这个镜像>

为基础 
FROM ubuntu

MAINTAINER Yongxin Li
COPY nginx-alpine.tar /opt/
WORKDIR /opt
#RUN命令会在上面指定的镜像里执行命令 
#RUN apt-get update && apt install -y nginx

#告诉docker,启动容器时执行如下命令
CMD ["/usr/sbin/nginx", "-g","daemon off;"]

构建镜像test:v1
#这里可以不加-f Dockerfile
[root@k8s-slave1 my-ubuntu-image]# docker build . -t test:v1
Sending build context to Docker daemon   25.1MB
Step 1/5 : FROM ubuntu
 ---> 2dc39ba059dc
Step 2/5 : MAINTAINER Yongxin Li
 ---> Using cache
 ---> df4b28edd20b
Step 3/5 : COPY nginx-alpine.tar /opt/
 ---> 5cf9a7d0a90e
Step 4/5 : WORKDIR /opt
 ---> Running in 8da7f69876e7
Removing intermediate container 8da7f69876e7
 ---> e784bb103745
Step 5/5 : CMD ["/usr/sbin/nginx", "-g","daemon off;"]
 ---> Running in 20a25ea921ad
Removing intermediate container 20a25ea921ad
 ---> 02ab69ab93ba
Successfully built 02ab69ab93ba
Successfully tagged test:v1

启动镜像并进入
下面是经常用来调试
WORKDIR的第一个含义是:默认进入容器的路径就是上面WORKDIR指定进入的路径
## --rm 容器退出来,docker会自动把容器删除
## -ti 启动容器时进入容器
[root@k8s-slave1 my-ubuntu-image]# docker run --rm -ti test:v1 /bin/sh
#
# pwd
/opt
# ls
nginx-alpine.tar

此时执行docker ps
[root@k8s-slave1 ~]# docker ps
CONTAINER ID   IMAGE             COMMAND                  CR            NAMES
04997d54cac2   test:v1           "/bin/sh"                23            busy_dhawan
7f8bfc2c02cc   my-nginx:ubuntu   "/usr/sbin/nginx -g …"   30            my-ubuntu-ngixn
18774d75a1df   registry:2        "/entrypoint.sh /etc…"   4 >5000/tcp   registry

再尝试退出容器

# pwd

/opt
#exit

由于启动时添加了--rm参数,此时发现docker已经自动删除了该容器
[root@k8s-slave1 ~]# docker ps
CONTAINER ID   IMAGE             COMMAND                  CREATED          STATUS          PORTS                                       NAMES
7f8bfc2c02cc   my-nginx:ubuntu   "/usr/sbin/nginx -g …"   47 minutes ago   Up 47 minutes                                               my-ubuntu-ngixn
18774d75a1df   registry:2        "/entrypoint.sh /etc…"   4 days ago       Up 4 days       0.0.0.0:5000->5000/tcp, :::5000->5000/tcp   registry

实操二:如果指定一个不存在的目录作为默认目录,构建镜像后将自动创建该目录

如果指定一个不存在的目录作为默认目录
[root@k8s-slave1 my-ubuntu-image]# vim Dockerfile 

# 告诉docker使用哪个基础镜像作为模板,后续命令都以这个镜像>

为基础 
FROM ubuntu

MAINTAINER Yongxin Li
WORKDIR /opt/myapp
COPY nginx-alpine.tar .

# RUN命令会在上面指定的镜像里执行命令 

#RUN apt-get update && apt install -y nginx

#告诉docker,启动容器时执行如下命令
CMD ["/usr/sbin/nginx", "-g","daemon off;"]

构建镜像
[root@k8s-slave1 my-ubuntu-image]# docker build . -t test:v2
Sending build context to Docker daemon   25.1MB
Step 1/5 : FROM ubuntu
 ---> 2dc39ba059dc
Step 2/5 : MAINTAINER Yongxin Li
 ---> Using cache
 ---> df4b28edd20b
Step 3/5 : WORKDIR /opt/myapp
 ---> Running in 2dbe3403774d
Removing intermediate container 2dbe3403774d
 ---> be6c01bcd3d0
Step 4/5 : COPY nginx-alpine.tar .
 ---> 964af9c7834d
Step 5/5 : CMD ["/usr/sbin/nginx", "-g","daemon off;"]
 ---> Running in 720f6a367760
Removing intermediate container 720f6a367760
 ---> 63eb54b0969f
Successfully built 63eb54b0969f
Successfully tagged test:v2

启动容器并进入,发现原来并不存在的/opt/myapp已经为默认目录,说明Dockerfile中的WORKDIR的第二个含义是自动创建指定的命令
[root@k8s-slave1 my-ubuntu-image]# docker run --rm -ti test:v2 /bin/sh
# 
# pwd
/opt/myapp
# ls
nginx-alpine.tar

RUN 构建镜像过程中执行命令

格式:
    RUN <command>
示例:
    RUN yum install nginx
    RUN pip install django
    RUN mkdir test && rm -rf /var/lib/unusedfiles
注意:
    RUN指令创建的中间镜像会被缓存,并会在下次构建中使用。如果不想使用这些缓存镜像,可以在构建时指定--no-cache参数,如:docker build --no-cache
即:
	RUN 指令是在docker built时候执行
	CMD 指令是在docker run时候执行

CMD 构建容器后调用,也就是在容器启动时才进行调用

格式:
    CMD ["executable","param1","param2"] (执行可执行文件,优先)
    CMD ["param1","param2"] (设置了ENTRYPOINT,则直接调用ENTRYPOINT添加参数)
    CMD command param1 param2 (执行shell内部命令)
示例:
    CMD ["/usr/bin/wc","--help"]
    CMD ping www.baidu.com
注意:
    CMD不同于RUN,CMD用于指定在容器启动时所要执行的命令,而RUN用于指定镜像构建时所要执行的命令。

ENTRYPOINT 设置容器初始化命令,使其可执行化

格式:
    ENTRYPOINT ["executable", "param1", "param2"] (可执行文件, 优先)
    ENTRYPOINT command param1 param2 (shell内部命令)
示例:
    ENTRYPOINT ["/usr/bin/wc","--help"]
注意:
    Dockerfile中只允许有一个ENTRYPOINT命令,多指定时会覆盖前面的设置,而只执行最后的ENTRYPOINT指令。
    
    ENTRYPOINT与CMD非常类似,不同的是:
    	通过docker run执行的命令不会覆盖ENTRYPOINT
    	通过docker run执行的命令会覆盖掉CMD。而docker run命令中指定的任何参数,都会被当做参数再次传递给ENTRYPOINT。
    	
    如果Dockerfile中同时存在CMD和ENTRYPOINT时,CMD指定的参数,会被添加作ENTRYPOINT的参数。

ENV指定环境变量

格式:
    ENV <key> <value>
    ENV <key>=<value>
示例:
    ENV myName John
    ENV myCat=fluffy

EXPOSE端口

格式:
    EXPOSE <port> [<port>...]
示例:
    EXPOSE 80 443
    EXPOSE 8080
    EXPOSE 11211/tcp 11211/udp
    EXPOES只是显示一个端口让外界知道(docker ps能显示出来),并不影响它本来的服务和端口的正常启动
    注意:
    EXPOSE并不会让容器的端口访问到主机。要使其可访问,需要在docker run运行容器时通过-p来发布这些端口,或通过-P参数来发布EXPOSE导出的所有端口

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jy1qplae-1678660765432)(http://49.7.203.222:3000/docker/images/Dockerfile%E8%A7%A3%E9%87%8A.png)]

  • 基础环境镜像

    FROM java:8-alpine
    
    RUN apk add --update ca-certificates && rm -rf /var/cache/apk/* && \
      find /usr/share/ca-certificates/mozilla/ -name "*.crt" -exec keytool -import -trustcacerts \
      -keystore /usr/lib/jvm/java-1.8-openjdk/jre/lib/security/cacerts -storepass changeit -noprompt \
      -file {} -alias {} \; && \
      keytool -list -keystore /usr/lib/jvm/java-1.8-openjdk/jre/lib/security/cacerts --storepass changeit
    
    ENV MAVEN_VERSION 3.5.4
    ENV MAVEN_HOME /usr/lib/mvn
    ENV PATH $MAVEN_HOME/bin:$PATH
    
    RUN wget http://archive.apache.org/dist/maven/maven-3/$MAVEN_VERSION/binaries/apache-maven-$MAVEN_VERSION-bin.tar.gz && \
      tar -zxvf apache-maven-$MAVEN_VERSION-bin.tar.gz && \
      rm apache-maven-$MAVEN_VERSION-bin.tar.gz && \
      mv apache-maven-$MAVEN_VERSION /usr/lib/mvn
    
    RUN mkdir -p /usr/src/app
    WORKDIR /usr/src/app
    
  • 前端镜像

    FROM nginx:1.19.0-alpine
    
    LABEL maintainer="mritd <mritd@linux.com>"
    
    ARG TZ='Asia/Shanghai'
    ENV TZ ${TZ}
    
    RUN apk upgrade --update \
        && apk add bash tzdata curl wget ca-certificates \
        && ln -sf /usr/share/zoneinfo/${TZ} /etc/localtime \
        && echo ${TZ} > /etc/timezone \
        && rm -rf /usr/share/nginx/html /var/cache/apk/*
    
    COPY dist /usr/share/nginx/html
    
    EXPOSE 80 443
    
    CMD ["nginx", "-g", "daemon off;"]
    
  • java镜像

    FROM java:8u111
    
    ENV JAVA_OPTS "\
    -Xmx4096m \
    -XX:MetaspaceSize=256m \
    -XX:MaxMetaspaceSize=256m"
    ENV JAVA_HOME /usr/java/jdk
    ENV PATH ${PATH}:${JAVA_HOME}/bin
    
    COPY target/myapp.jar myapp.jar
    
    RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
    RUN echo 'Asia/Shanghai' >/etc/timezone
    
    EXPOSE 9000
    CMD java ${JAVA_OPTS} -jar myapp.jar
    
  • golang镜像

    多阶段构建

    总结:CMD、ENTRYPOINT一定是可持续运行的命令。

通过1号进程理解容器的本质

容器中看是1号进程
[root@k8s-slave1 ~]# docker exec -ti my-ubuntu-nginx /bin/sh
# 
# ps aux
USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root          1  0.2  0.1  55144  6376 ?        Ss   14:07   0:00 nginx: master process /usr/sbin/nginx -g daemon off;
www-data      7  0.0  0.0  55512  2288 ?        S    14:07   0:00 nginx: worker process
www-data      8  0.0  0.0  55512  2028 ?        S    14:07   0:00 nginx: worker process
root          9  0.2  0.0   2872   508 pts/0    Ss   14:07   0:00 /bin/sh
root         15  0.0  0.0   7044  1444 pts/0    R+   14:07   0:00 ps aux
#

宿主机上看是19568进程
[root@k8s-slave1 ~]# docker inspect my-ubuntu-nginx|grep Pid
            "Pid": 19568,
            "PidMode": "",
            "PidsLimit": null,

[root@k8s-slave1 ~]# ps -ef|grep 19568
root      19568  19547  0 22:07 ?        00:00:00 nginx: master process /usr/sbin/nginx -g daemon off;
33        19596  19568  0 22:07 ?        00:00:00 nginx: worker process
33        19597  19568  0 22:07 ?        00:00:00 nginx: worker process
root      20394  19659  0 22:09 pts/1    00:00:00 grep --color=auto 19568

说明容器内部是有一套独立的进程空间

容器启动的时候可以通过命令去覆盖默认的CMD

启动nginx:alpine镜像,name为test
[root@k8s-slave1 ~]# docker run -d --name test-3 nginx:alpine echo 123
0c8cce5ace15688fa395849722e15617b536e01bfa59bbb66b1deead8fb21d2e

发现没有找到test-3
[root@k8s-slave1 ~]# docker ps
CONTAINER ID   IMAGE                                  COMMAND                  CREATED          STATUS          PORTS                                       NAMES
cda9d9d9baa3   192.168.178.131:5000/my-nginx:ubuntu   "/usr/sbin/nginx -g …"   40 minutes ago   Up 40 minutes                                               test
169855258d24   nginx:alpine                           "/docker-entrypoint.…"   42 minutes ago   Up 42 minutes   80/tcp                                      my-nginx
18774d75a1df   registry:2                             "/entrypoint.sh /etc…"   6 days ago       Up 48 minutes   0.0.0.0:5000->5000/tcp, :::5000->5000/tcp   registry
d654802d28ce   my-nginx:ubuntu                        "/usr/sbin/nginx -g …"   13 days ago      Up 7 minutes    0.0.0.0:8088->80/tcp, :::8088->80/tcp       my-ubuntu-nginx

[root@k8s-slave1 ~]# docker ps -a
CONTAINER ID   IMAGE                                  COMMAND                  CREATED          STATUS                        PORTS                                       NAMES
0c8cce5ace15   nginx:alpine                           "/docker-entrypoint.…"   19 seconds ago   Exited (0) 17 seconds ago                                                 test-3
cda9d9d9baa3   192.168.178.131:5000/my-nginx:ubuntu   "/usr/sbin/nginx -g …"   40 minutes ago   Up 40 minutes                                                             test
169855258d24   nginx:alpine                           "/docker-entrypoint.…"   42 minutes ago   Up 42 minutes                 80/tcp                                      my-nginx
6ea65b17c0ee   my-nginx:ubuntu                        "/usr/sbin/nginx -g …"   24 hours ago     Exited (255) 48 minutes ago                                               frosty_mcnulty
6706e0d6d1db   test:v1                                "/usr/sbin/nginx -g …"   24 hours ago     Created                                                                   gallant_northcutt
e64af2d9ab97   test:v2                                "/usr/sbin/nginx -g …"   24 hours ago     Created                                                                   naughty_brattain
dceccb291eec   test:v2                                "--name testv2"          25 hours ago     Created                                                                   friendly_moser
76ab1e8cb62d   test:v2                                "-name testv2"           25 hours ago     Created                                                                   jolly_tharp
dafe4b79fe1a   test:v2                                "/usr/sbin/nginx -g …"   25 hours ago     Created                                                                   distracted_torvalds
7f8bfc2c02cc   my-nginx:ubuntu                        "/usr/sbin/nginx -g …"   26 hours ago     Exited (255) 24 hours ago                                                 my-ubuntu-ngixn
18774d75a1df   registry:2                             "/entrypoint.sh /etc…"   6 days ago       Up 48 minutes                 0.0.0.0:5000->5000/tcp, :::5000->5000/tcp   registry
35197b0c8704   portainer/portainer                    "/portainer"             13 days ago      Exited (2) 7 days ago                                                     portainer
d654802d28ce   my-nginx:ubuntu                        "/usr/sbin/nginx -g …"   13 days ago      Up 7 minutes                  0.0.0.0:8088->80/tcp, :::8088->80/tcp       my-ubuntu-nginx

注意:test-3容器立即关闭,是因为echo 123覆盖了镜像中指定的CMD指令(Dockerfile原指定了CMD为nginx -g daemon off),作为了1号进程。而且echo 123执行完毕就会退出,导致容器的1号进程结束,从而容器关闭

如果ping www.baidu.com命令作为1号进程,由于执行该命令不会退出,容器不会立即关闭
[root@k8s-slave1 ~]# docker run -d --name test-4 nginx:alpine ping www.baidu.com
a858259199b855e1364f1fcae4d0d0091cb75d01312a5a12fb66c0a222ac49cc
[root@k8s-slave1 ~]# docker ps
CONTAINER ID   IMAGE                                  COMMAND                  CREATED          STATUS          PORTS                                       NAMES
a858259199b8   nginx:alpine                           "/docker-entrypoint.…"   6 seconds ago    Up 5 seconds    80/tcp                                      test-4
cda9d9d9baa3   192.168.178.131:5000/my-nginx:ubuntu   "/usr/sbin/nginx -g …"   42 minutes ago   Up 42 minutes                                               test
169855258d24   nginx:alpine                           "/docker-entrypoint.…"   44 minutes ago   Up 44 minutes   80/tcp                                      my-nginx
18774d75a1df   registry:2                             "/entrypoint.sh /etc…"   6 days ago       Up 51 minutes   0.0.0.0:5000->5000/tcp, :::5000->5000/tcp   registry
d654802d28ce   my-nginx:ubuntu                        "/usr/sbin/nginx -g …"   13 days ago      Up 10 minutes   0.0.0.0:8088->80/tcp, :::8088->80/tcp       my-ubuntu-nginx


$ docker run -d --name xxx nginx:alpine <自定义命令>
# <自定义命令>会覆盖镜像中指定的CMD指令,作为容器的1号进程启动。

$ docker run -d --name test-3 nginx:alpine echo 123

$ docker run -d --name test-4 nginx:alpine ping www.luffycity.com

本质上讲容器是利用namespace和cgroup等技术在宿主机中创建的独立的虚拟空间,这个空间内的网络、进程、挂载等资源都是隔离的。

$ docker exec -ti my-nginx /bin/sh
#/ ip addr
#/ ls -l /
#/ apt install xxx
#/ #安装的软件对宿主机和其他容器没有任何影响,和虚拟机不同的是,容器间共享一个内核,所以容器内没法升级内核

小结

dockerfile里面的CMD、ENTRYPOINT以及对构建好的镜像执行docker run的命令一定是可持续运行的命令,否则导致容器启动后无法持续运行且退出。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值