Docker学习笔记(二)

这次要学习的主要是Dockerfile,感觉就是很像命令行似的东西。这东西单看起来就有点像是构建命令,基本上在大写关键字后跟的东西就是系统命令行。

FROM ubuntu:latest
RUN apt-get update && \
    DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y python3.9 python3-pip python3.9-dev
ADD test.py  /
CMD ["python3","test.py"]

上面所示的就是一段最简单的Dockerfile,首先是找一个基础镜像,再安装Python3,最后运行一个python脚本。然后运行docker image build -t xxx就可以运行Dockerfile,生成一个名为xxx的镜像。可以看到在关键字后面跟的就是在基础镜像里面可以运行的命令。所以理解起来也不是很难,所谓的Dockerfile就是可以对基础镜像进行自己的自定义打包,生成新的镜像的命令文件。

命令补充

docker image tag old new 镜像改名

docker login 登录Dockerhub(需要事先申请Dockerhub的账号)

docker image push xxx 镜像上传到Dockerhub

关键字解析和注意事项

FROM引入的原则:1.优先官方镜像 2.tag要标清楚 3.功能满足的情况下镜像尽量小

RUN的功能:运行shell命令。要注意的是,运行多个命令,最好不要每条命令都RUN一下,因为每RUN一次,容器都会进行一次分层。这样的话,容器的体量就会很大。要连接多条命令,可以用&& \来连接。

命令补充

docker image history <Image ID>查看image的封装历史(层数)

docker image build -f dockerfile.good -t ipinfo-good .构建镜像

-f主要是因为Dockerfile命名不是默认的Dockerfile,需要指明具体的文件。

文件操作命令:使用COPY或ADD命令来添加本地的文件到镜像中,像是上面举过的例子,添加当前目录中的文件到镜像中路径,当路径不存在就会自动创建。

COPY和ADD使用的时候其实没有什么区别,就是ADD添加的gzip压缩文件到镜像会自动解压,这样的话多文件上传就会很方便。

切换目录命令:WORKDIR命令会切换在镜像中的路径,相当于在镜像中运行cd命令。

定义变量:ARG和ENV命令,这两个命令都是可以用来定义变量的,但是在使用细节上有一点区别。变量的使用主要是命令中可能存在的诸如版本号修改一类的东西,使用变量引入的话会方便修改。ENV VERSION=2.0.1就是像这样的定义格式。用$(VERSION)在命令中引入变量。

ARG的声明变量结构和上面ENV的例子类似。

ARG和ENV的区别一是声明变量的作用域不同,ENV的变量是可以直接带入到镜像中的,用env命令可以直接查看到定义的变量。二是ARG声明后可以在构建时修改变量。在build镜像时,用--build-arg xxx=xx来直接修改版本号,方便了生成其他版本的镜像。

默认执行命令:CMD可以用来设置容器启动时候默认会执行的命令。

命令补充

docker system prune -f批量删除已经退出的容器

docker image prune -a删除没有使用的所有镜像

若docker container run启动容器时指定了其他命令,则CMD命令会被忽略,定义了多个CMD则只有最后一个CMD会执行。

上面说了,可以直接在启动容器的时候指定容器开启时执行的命令,举个例子:docker container run -it ipinfo-base ipinfo version就是在开启后运行ipinfo version这条命令。在Dockerfile中写成CMD形式CMD ["ipinfo","version"]。

ENTRYPOINT命令同样也可以设置容器启动时候要执行的命令,但和CMD有一点区别。CMD执行的命令可以在运行容器时通过传入命令覆盖掉,但是ENTRYPOINT的命令一定会执行。这两个命令可以同时使用。ENTRYPOINT设置命令,CMD设置参数。就像下面的例子:

FROM ubuntu:21.04
ENTRYPOINT [ "echo"]
CMD []

这样的话,CMD实际决定了输出的内容是什么。可以通过运行容器时候输入的内容在界面上进行相应的输出。

数据持久化

所谓的数据持久化,指的就是在容器中的数据在容器被删除之后,依旧可以被之后创建的新容器使用,从而不会丢失。

在Dockerfile中添加VOLUME可以将数据持久化,这样即使容器被删除了,数据依旧存在。开启的新的容器依然可以使用。

一般的用法

用VOLUME可以设置容器中持久化的目录。举例,在Dockerfile中使用VOLUME ["/app"]来固定/app目录。在开启的容器中创建app目录并且添加文件,这些文件在容器删除后就不会丢失掉了。

命令补充

docker volume ls列出所有的持久化空间,其中会列出诸如持节话空间的名字,还有所处的路径(挂载点)。

想让新容器利用旧容器的持久化空间?在启动容器的时候给空间起个名字,用-v来命名。docker container run -d -v my-data:/app my-image,-v后面接的是命名和空间的路径。这样的话,生成的空间就可以被继承了。用列出命令获得的路径名称也就不会是生成的一串随机码。

Bind Mount数据持久化

这种方式叫做挂载绑定,可以把容器中持久化的数据绑定到本机的自定义位置。Data Volume在Windows环境中使用很不方便,因为想想就知道这种用法对应的路径只有在Linux下比较好用,对应到Windows环境就会非常奇怪。而且Bind Mount的设置更简单,可以和开发环境更好的融合。所以建议多使用Bind Mount来实现数据持久化。这种方法也是要用-v参数,像是docker container run -it -v ${pwd}:/app node就是将容器中的/app目录和本机的当前目录绑定到了一起。这样的话就可以在本机当前目录添加和操作内容,在容器中运行。

这样的话,其实就是很像现在开发中用的在本地环境创建一个网络共享文件夹,可以本地编辑代码,在容器中看效果,或者说容器中做一些操作,本地中也会有反映。感觉很方便开发。

总结

这章主要是把Dockerfile的用法学了一下,还有数据持久化的相关了解,总体来说都是为了生成镜像。说实话让我自己去搭一个镜像,像是Laravel开发这种镜像,感觉要死,要求的东西太多了。目前还是以拿来用作为目的就好了。