Dockerfile
Dockerfile就是用来创建Docker镜像的定义文件。在Dockerfile中有一条条构建镜像所需要的指令和参数所需要的脚本。
在Dockerfile中的每条指令都会构建一个新的镜像层并对镜像进行提交。因此Docker执行Dockerfile的流程也是类似的,每执行一条指令都会提交一个镜像层,然后Docker会基于刚提交的镜像运行一个新容器,如此往复,直到Dockerfile中的所有命令都运行完毕为止。
可以说Dockerfile主要针对开发人员
Docker镜像是包含软件和运行环境的一个产品
Docker容器则是真正部署到开发/产品环境的最终运行态产品
FROM(构建时)
在创建自己的镜像时,通常需要在现有镜像基础上构建,比如:
FROM node:lts-alpineENV(运行时)
在这里可以添加环境变量,比如:
ENV MONGO_DB_USERNAME=admin \
MONGO_DB_PWD=password但建议不在这里定义环境变量,而是在docker-compose.yml中定义,这样一旦环境变量发生变化,无需重新构建docker镜像。
RUN(构建时)
可以通过RUN来运行任何Linux Shell命令,比如:
RUN mkdir -p /home/lcoding/app注意:这些命令都是在容器中运行的,而不是在host中运行。比如:上面的RUN命令会在容器中创建/home/lcoding。
在执行RUN命令的时候,还可以同时传递一些参数,比如:
RUN ["./process_data.py", "demo.csv"]COPY(构建时)
COPY命令用于将host中的文件复制到容器中,例如:
COPY . /home/lcoding/appADD(构建时)
将宿主机目录下的文件复制到镜像中,同时自动处理URL及解压tar压缩包。
ADD = COPY + 解压
CMD(运行时)
运行一个入口命令(容器启动后运行的命令):
CMD ["node", "server.js"]在一个Dockerfile中,可以有多个RUN命令(RUN是在构建镜像时运行,但CMD是在容器运行时被执行的。),但只能有一个CMD命令(其实也可以添加多个CMD命令,但只有最后一个会起作用)。也正是因为这个原因,如果在启动容器的时候指定了需要运行的命令,将会覆盖这个CMD命令。比如,在启动Tomcat时运行:
docker run -it tomcat /bin/bash就会覆盖Tomcat镜像中的最后一条命令(CMD [“catalina.sh”, “run”]),进而使得Tomcat无法正常服务。
ENTRYPOINT(运行时)
ENTRYPOINT和CMD命令类似,但ENTRYPOINT不会被docker run所指定的命令所覆盖,而将这些命令当作参数传递给ENTRYPOINT。与此类似,如果同时有CMD和ENTRYPOINT,CMD命令所指定的命令将被作为参数传递给ENTRYPOINT。
EXPOSE(运行时)
指定当前容器对外暴露的端口
WORKDIR(构建及运行时)
指定通过终端登录进容器后的初始目录
USER(构建及运行时)
指定以哪个用来运行镜像,如果未指定的话,默认为root
完整的Dockerfile
在APP源文件的根目录下创建Dockerfile:
FROM node:13-alpine
ENV MONGO_DB_USERNAME=admin \
MONGO_DB_PWD=12345
RUN mkdir -p /home/lcoding/app
COPY . /home/lcoding/app
CMD ["node", "/home/lcoding/app/server.js"]其构建的镜像层级结构如下:
- app:1.0
- node:13-alpine
- alpine:3.10
通过Dockerfile创建镜像
docker build -t lcoding-demo:1.0 .至此,再使用docker images命令就可以看到在本地的镜像仓库中已经有lcoding-demo这个image了。
测试自己的镜像
docker run lcoding-demo:1.0可以改进的地方
当启动容器后,其实并不需要Dockerfile,docker-compose.yml等文件。因此可以单独创建一个app文件夹,同时在创建Dockerfile的时候,只将app文件夹中的文件复制到容器中即可。
COPY ./app/* /home/lcoding/app