【Docker】Dockerfile的基本用法

233 阅读6分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第18天,点击查看活动详情

上节【Docker】基础知识入门中给大家介绍了Docker中的镜像容器仓库,本节将完成通过Dockerfile制作自己的镜像,并且在容器中运行,最后上传到官网仓库中。

编写Dockerfile制作镜像

Dokcerfile就是用来构建docker镜像的构建文件,由不同的命令组成。这里制作一个简单flask项目的的镜像。(flask是一个轻量级的python web框架,感兴趣的可以在官网了解)。

首先先在本地将Flask项目运行起来,主要有以下几步:

  • 安装Python,这里使用的版本是python 3.9
  • 使用命令pip install Flask安装Flask依赖
  • 创建一个python文件app.py,编写代码如下:
from flask import Flask

app = Flask(__name__)


@app.route("/")
def hello_world():
    return "<p>Hello, World!</p>"
  • 使用使用命令flask run将应用运行起来,可以看到其默认端口为5000

  • 最后使用浏览器访问,正确输出Hello World,则说明运行成功。

本地调试通过,接下来就是制作镜像了,主要有以下几步:

  • 在服务器新建一个文件夹,docker_app,然后将本地文件``app.py上传到文件夹,同时在目录中新建文件Dockerfile```。

  • 编辑Dockerfile文件,这里可以和上面本地运行Flask的步骤进行对比:
# 基于python:3.9基础镜像进行构建——>相当于本地安装python 3.9
FROM python:3.9
# 运行命令——>相当于本地使用命令安装Flask
RUN pip install Flask -i https://pypi.douban.com/simple/
# 设置容器工作目录
WORKDIR /root/dev/app
# 拷贝命令 将当前目录的文件全部拷贝到容器内的目录中,即将app.py拷贝到/root/dev/app目录中
COPY . /root/dev/app
# 容器内运行命令——>相当于本地启动flask项目,-h参数指定外网可访问
ENTRYPOINT flask run -h 0.0.0.0 
  • 保存Dockerfile文件后,在目录中执行命令docker build -t helloapp:v1 .制作镜像(默认Dockerfile文件为本目录下的名为Dockerfile的文件,所以这里可以省略)-t参数用来指定镜像名称:tag
[root@iZwz95h9ihcvtbglpnnhx9Z docker_app]# docker build -t helloapp:v1 .
Sending build context to Docker daemon  3.072kB
Step 1/5 : FROM python:3.9
 ---> 9fa3494cf8c7
Step 2/5 : RUN pip install Flask -i https://pypi.douban.com/simple/
 ---> Running in 8eadc25c3051
Looking in indexes: https://pypi.douban.com/simple/
...
Removing intermediate container 8eadc25c3051
 ---> 839bfecf8be7
Step 3/5 : WORKDIR /root/dev/app
 ---> Running in 464c0c9d5fc0
Removing intermediate container 464c0c9d5fc0
 ---> 30542f6592fe
Step 4/5 : COPY . /root/dev/app
 ---> fda980746504
Step 5/5 : ENTRYPOINT flask run -h 0.0.0.0
 ---> Running in 74b1af379071
Removing intermediate container 74b1af379071
 ---> 796782e98616
Successfully built 796782e98616
Successfully tagged helloapp:v1

从日志中可以看到,根据Dockerfile中的命令,一步一步进行了操作,也就是所谓的分层,可以看到很多Running in xxxRemoving intermediate container xxx,这是因为每一步命令其实都是基于上一层临时创建了容器,在容器中进行操作后打包生成新的中间层镜像,然后删除临时容器。

现在将Dockerfile文件修改如下:

# 基于python:3.9基础镜像进行构建——>相当于本地安装python 3.9
FROM python:3.9
# 运行命令——>相当于本地使用命令安装Flask
RUN pip install Flask -i https://pypi.douban.com/simple/
# 设置容器工作目录
WORKDIR /root/dev/app
# 拷贝命令 将当前目录的文件全部拷贝到容器内的目录中,即将app.py拷贝到/root/dev/app目录中
COPY . /root/dev/app
# 指定容器暴露端口
EXPOSE 5000
# 容器内运行命令——>相当于本地启动flask项目,-h参数指定外网可访问
ENTRYPOINT flask run -h 0.0.0.0 

再次运行命令docker build -t helloapp:v1.1 .制作镜像,修改tag为1.1,再次查看日志,可以看到在第5步之前,未改动的步骤,都是Using cache即使用上一次的缓存,不再需要重新进行执行。但是后面步骤依然要创建临时容器执行命令删除容器。

[root@iZwz95h9ihcvtbglpnnhx9Z docker_app]# docker build -t helloapp:v1.1 .
Sending build context to Docker daemon  3.584kB
Step 1/6 : FROM python:3.9
 ---> 9fa3494cf8c7
Step 2/6 : RUN pip install Flask -i https://pypi.douban.com/simple/
 ---> Using cache
 ---> 839bfecf8be7
Step 3/6 : WORKDIR /root/dev/app
 ---> Using cache
 ---> 30542f6592fe
Step 4/6 : COPY . /root/dev/app
 ---> 7a59bdbc3024
Step 5/6 : EXPOSE 5000
 ---> Running in 852f9f37145c
Removing intermediate container 852f9f37145c
 ---> 6dc5b1b2cd17
Step 6/6 : ENTRYPOINT flask run -h 0.0.0.0
 ---> Running in 49c86307491a
Removing intermediate container 49c86307491a
 ---> 6b7f230886b3
Successfully built 6b7f230886b3
Successfully tagged helloapp:v1.1
  • 镜像创建完成后,通过命令docker images可以看到服务器上的镜像,如下,出现我们自己命名的镜像,则说明镜像制作完成。

启动容器

  • 刚刚已经制作了我们自己的镜像,现在就可以通过命令docker run -d -p 80:5000 --name app helloapp:v1.1来启动镜像了,-d参数用于指定容器在后台运行,-p 服务器端口:容器内端口参数将容器内端口映射到服务器端口上,以便可以直接通过服务器IP进行访问,--name参数指定容器名称,最后是指定镜像名称和tag。

  • 启动成功后,使用命令docker ps查看服务器上运行的容器,如下

  • 通过浏览器访问http://服务器IP:80,跟本地一样可以正常输出“Hello World”,则启动成功

上传仓库

现在镜像已经制作完成,并且在服务上启动容器验证通过了,然后就可以将镜像上传到镜像仓库给其他人使用了,通常公司内部会搭建自己的镜像仓库,这里演示就是用官方提供的Docker Hub

  • 要上传镜像,需要先在Docker Hub上注册并登录,登录后点击"Create repository",输入对应的仓库名称和描述后选择创建

  • 在服务器终端使用命令docker login,输入自己的用户名和密码进行登录。

  • 使用命令docker tag local-image:tagname new-repo:tagname给本地的镜像打上tag,new-repo就是上面的用户名/仓库名称

  • 然后就可以使用命令docker push new-repo:tagname上传镜像了。

  • 上传成功后,可以查看docker hub页面,可以看到刚上传的tag,如下:

  • 现在可以测试一下,使用命令docker rmi image_name将本地的镜像删掉,使用docker pull new-repo:tagname拉取刚上传的镜像到本地

  • 将之前的容器关闭删除后,使用下载的镜像再次启动,访问浏览器,可以看到和之前本地镜像的效果是一致的。

到这里就完成一个简单应用的镜像制作、容器运行、和仓库上传/下载啦,撒花🎉🎉🎉