应用容器化
容器是为应用而生!具体来说,容器能够简化应用的构建、部署和运行过程。
容器化步骤
完整的应用容器化过程主要分为以下几个步骤。
- 编写应用代码。
- 创建一个
Dockerfile
,其中包括当前应用的描述、依赖以及该如何运行这个应用。 - 对该
Dockerfile
执行docker image build
命令。 - 等待
Docker
将应用程序构建到Docker
镜像中。
Dockerfile文件分析
Dockerfile的两个用途
- 对当前应用的描述。
- 指导
Docker
完成应用的容器化(创建一个包含当前应用的镜像)。
编写准则:
- 构建上下文:在
Docker
当中,包含应用文件的目录通常被称为构建上下文(Build Contex
t)。通常将Dockerfile
放到构建上下文的根目录下。 -
Dockerfile
:开头字母是大写D
,这里是一个单词。像“dockerfile”
或者“Docker file”
这种写法都是不允许的
文件分析
# Test web-app to use with Pluralsight courses and Docker Deep Dive book
# Linux x64
FROM alpine
LABEL maintainer="nigelpoulton@hotmail.com"
# Install Node and NPM
RUN apk add --update nodejs nodejs-npm
# Copy app to /src
COPY . /src
WORKDIR /src
# Install dependencies
RUN npm install
EXPOSE 8080
ENTRYPOINT ["node", "./app.js"]
以alpine镜像作为当前镜像基础,指定维护者(maintainer)为“nigelpoultion@hotmail.com”,安装Node.js和NPM,将应用的代码复制到镜像当中,设置新的工作目录,安装依赖包,记录应用的网络端口,最后将app.js设置为默认运行的应用。
-
FROM
:FROM指令指定的镜像,会作为当前镜像的一个基础镜像层,当前应用的剩余内容会作为新增镜像层添加到基础镜像层之上。
-
LABLE
:Dockerfile中通过标签(LABLE)方式指定了当前镜像的维护者为“nigelpoulton@hotmail. com”
-
RUN
:RUN apk add --update nodejs nodejs-npm
指令使用alpine的apk包管理器将nodejs和nodejs-npm安装到当前镜像之中
-
COPY
:COPY. / src
指令将应用相关文件从构建上下文复制到了当前镜像中
WORKDIR
:WORKDIR指令,为Dockerfile中尚未执行的指令设置工作目录。该目录与镜像相关,并且会作为元数据记录到镜像配置中,但不会创建新的镜像层。-
RUN
:RUN npm install
指令会根据package.json中的配置信息,使用npm来安装当前应用的相关依赖包。npm命令会在前文设置的工作目录中执行,并且在镜像中新建镜像层来保存相应的依赖文件
EXPOSE
:当前应用需要通过TCP端口8080对外提供一个Web服务,所以在Dockerfile中通过EXPOSE 8080指令来完成相应端口的设置。这个配置信息会作为镜像的元数据被保存下来,并不会产生新的镜像层ENTRYPOINT
:ENTRYPOINT指令来指定当前镜像的入口程序。ENTRYPOINT指定的配置信息也是通过镜像元数据的形式保存下来,而不是新增镜像层
新增镜像层的指令包括
FROM
、RUN
以及COPY
,而新增元数据的指令包括EXPOSE
、WORKDIR
、ENV
以及ENTERPOINT
。关于如何区分命令是否会新建镜像层,一个基本的原则是,如果指令的作用是向镜像中增添新的文件或者程序,那么这条指令就会新建镜像层;如果只是告诉Docker如何完成构建或者如何运行应用程序,那么就只会增加镜像的元数据
命令
构建镜像
# 构建并生成一个名为web:latest的镜像
docker image build -t web:latest .
- 命令最后的点
(.)
表示Docker
在进行构建的时候,使用当前目录作为构建上下文,在执行命令前,读者要确认当前目录是应用根目录(包含Dockerfile
和应用代码的目录)
查看构建
docker image history web:latest
- 查看在构建镜像的过程中都执行了哪些指令,每行内容都对应了
Dockerfile
中的一条指令(顺序是自下而上)。CREATEBY
这一列中还展示了当前行具体对应Dockerfile中的哪条指令,输出内容中,可以观察到哪些指令会新建镜像层(就是那些SIZE列对应的数值不为零的指令),虽然其他指令看上去跟这些新建镜像层的指令并无区别,但实际上它们只在镜像中新增了元数据信息。这些指令之所以看起来没有区别,是因为Docker对之前构建镜像层方式的兼容。
docker image inspect web:latest
- 确认刚刚构建的镜像配置是否正确。这个命令会列出
Dockerfile
中设置的所有配置项,可以看到有几层镜像
推送构建到dockerHub
- 登录
DockerHub
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: testerlp
Password:
Login Succeeded
-
为待推送镜像打上合适的标签
-
Registry
(镜像仓库服务) -
Repository
(镜像仓库) -
Tag
(镜像标签)
无须为
Registry
和Tag
指定值。如果没有为上述信息指定具体值的时候,Docker会默认Registry=docker.io
、Tag=latest
。但是Docker并没有给Repository提供默认值,而是从被推送镜像中的REPOSITORY
属性值获取查看待推送镜像信息
docker images | grep alpine
-
docker image ls
命令。在该命令对应的输出内容中可以看到,镜像仓库的名称是alpine
。这意味着执行docker image push
命令,会尝试将镜像推送到docker.io/alpine:latest
中。但是其实testerlp
这个用户并没有alpine
这个镜像仓库的访问权限,所以只能尝试推送到testerlp
这个二级命名空间(Namespace
)之下。因此需要使用testerlp
这个ID
,为当前镜像重新打一个标签。
-
打tag
docker image tag web:latest testerlp/alpine:latest
格式是
docker image tag <current-tag> <new-tag>
,其作用是为指定的镜像添加一个额外的标签,并且不需要覆盖已经存在的标签 -
打完标签后查看镜像信息
docker images | grep alpine
- 推送镜像
docker image push testerlp/alpine:latest
ps:虽然超时了~~~