AberSheeran
Aber Sheeran
I know nothing except the fact of my ignorance.

Docker初尝试

起笔自
所属文集: Docker学习笔记
共计 4007 个字符
落笔于

其实两年前就想学Docker了,也早早的就在Windows10上装好了Docker。到现在才开始学,我的懒癌已经没有救了。

Docker

在我个人的理解里,Docker是一种对系统环境的模拟。无论是哪种Linux发行版,其内核都是大同小异的。借助这一事实,Docker只需要对Linux发行版的环境进行模拟,就可以使用宿主机的内核 + Docker镜像(image)的环境模拟一个让应用程序觉得真实的系统出来。

在Windows上,Docker借助了Hyper-V来创建一个Linux虚拟机来获得Linux内核。

理解了这一点,Docker本身其实就不难懂。至于其他的坑,或者优化,只能在实践中去获知了。

第一步

安装Docker,教程很多,搜一下就行。

安装并启动之后,在命令行中使用docker info来查看docker的一些信息。

一切正常,可以进行后面的操作了。

第二步

建立一个空白的文件夹,在其中建立名为Dockerfile的文本文件。写入以下内容

FROM ubuntu:18.04

RUN apt-get update \
    && apt-get install -y python3.6 \
    && apt-get install -y python3-pip

Docker会依次执行Dockerfile中的指令,文件中的第一条指令必须是FROM。FROM指令用于指定其后构建新镜像所使用的基础镜像,启动构建流程后,Docker将会基于该镜像构建新镜像,FROM后的命令也会基于这个基础镜像。当本机没有找到对应镜像时,会自动从远程的docker.hub进行查找、拉取。

而RUN指令,顾名思义,是在基础镜像里执行后面的命令。

如果你想使用我以此Dockerfile构建并发布的镜像,可以使用

FROM abersheeran/python3:latest

基础镜像的指定由几个部分组成:

  1. 镜像的所有者名称,当没有指定的时候,默认是library,也就是官方镜像。
  2. 镜像的名称。
  3. 镜像的版本,当没有指定的时候,默认是latest

此处我选择了我较为熟悉的Ubuntu18.04,当然你也可以使用其他的镜像,例如CentOS

docker build -t abersheeran/python3 .

在命令行中执行如上命令,docker会使用当前路径下的Dockerfile进行构建镜像。在此我使用-t选项指定构建的镜像为abersheeran/python3abersheeran是我的docker用户名,你最好改成你自己的。在这里没有指定构建所得的镜像的版本,所以默认是latest

执行这些命令之后,我们拥有一个预装了Python3.6的Ubuntu18.04的docker镜像了。使用docker image ls可以查看宿主机上拥有的镜像列表。

现在,这个镜像已经完成了它的任务,可以使用docker image rm IMAGE-ID来移除它。

第三步

使用一个小项目,进行真实的打包。这里我们模仿Docker官方教程中的Dockerfile进行编写。

我选择使用我用Sanic写过的upload作为练手第一作。这个项目本身是由pipenv进行环境与依赖管理的,但如果打包成docker镜像,就没必要再去使用虚拟环境,徒增镜像的大小。

编写Dockerfile如下:

FROM ubuntu:18.04

# 设置当前工作路径为/app,如果/app不存在会自动创建
WORKDIR /app

# 复制宿主机当前路径下内容到容器中的/app
COPY . /app

# 安装Python环境与requirements.txt中指定的包
RUN apt-get update \
    && apt-get install -y git \
    && apt-get install -y python3.6 \
    && apt-get install -y python3-pip \
    && pip3 install -r requirements.txt

# 告诉用户80端口会提供服务
EXPOSE 80

# 定义环境变量的值
ENV MEDIA_URL="https://image.abersheeran.com/" \
    MEDIA_DIR="/app/image"

# 当容器启动的时候,默认执行这个命令
# 注意:如果有多个CMD,仅有最后一个有效
CMD ["python3", "manage.py", "--host=0.0.0.0", "--port=80", "start"]

此时注意到虚拟环境所在的.venv不应该拷贝进容器,需要配置一下。在项目根目录下创建一个文本文件.dockerignore,与.gitignore类似的语法,写入规则排除指定的文件不收集到容器中

.venv/
.vscode/

最后使用docker build -t upload .来构建镜像。

优化Dockerfile

注意到多次构建时,有Using cache的显示。原来docker的镜像有一个层级的概念,当构建的一个层级没有变化时,docker会自动使用已经存在的层级,并不会重新构建。但如果某一个层级发生变化,那么从这之后的层级全部要重新构建。对镜像的文件系统造成更改的命令都会建立新的层级,例如:WORKDIRCOPYRUN

考虑到配置环境是十分耗时的,我们可以考虑把这一步骤尽可能地放在前面,这样一来,如果只是修改项目的代码,就不需要重新下载并配置环境。

FROM ubuntu:18.04

# 安装Python环境与git
RUN apt-get update \
    && apt-get install -y git \
    && apt-get install -y python3.6 \
    && apt-get install -y python3-pip \

# 设置当前工作路径为/app,如果/app不存在会自动创建
WORKDIR /app

# 复制宿主机当前路径下的requirements.txt
COPY requirements.txt ./

# 安装requirements.txt中指定的包
RUN pip3 install -r requirements.txt

# 复制宿主机当前路径下内容到容器中的/app
COPY . /app

# 告诉用户80端口会提供服务
EXPOSE 80

# 定义环境变量的值
ENV MEDIA_URL="https://image.abersheeran.com/" \
    MEDIA_DIR="/app/image"

# 当容器启动的时候,默认执行这个命令
# 注意:如果有多个CMD,仅有最后一个有效
CMD ["python3", "manage.py", "--host=0.0.0.0", "--port=80", "start"]

第四步

一个镜像构建好,我们肯定先要本地运行试试能不能正常运行。

docker run -v  ~/Documents/Github/image:/app/image -p 5000:80 upload

在这里,使用了-v选项将宿主机的文件系统共享给docker容器,把~/Documents/Github/image映射到/app/image,docker容器中的程序操作/app/image时,实际上是在~/Documents/Github/image中运行,这样就可以在宿主机的目录下提前初始化好git,使得此容器运行时使用的git commitgit push命令无需多余输入。

使用-p选项将docker容器的80端口映射到宿主机的5000端口。

在非Windows系统上,你还可以使用-d指定此容器在后台运行。

测试完之后,需要停止容器。在非Windows系统,或许直接用Ctrl+C就可以停止。但Windows上只能手动停止。

使用如下命令可以看到关于容器的一些信息

docker container ls

可以使用docker container stop CONTAINER-ID停止指定的容器。

清理

使用docker image ls发现有很多<none>的image,占据了一定的空间。使用这两条命令可以清理无用的容器与镜像。

# 清理无用的容器
docker container prune
# 清理无用的镜像
docker image prune

第五步

在不同机器间传递image,使用pushpull是一个好办法,但是对于不想公开的镜像,这要求你得有个私有库。很麻烦,个人开发没必要折腾。

使用docker save upload -o upload.tar可以将upload镜像保存在upload.tar文件中。

使用docker load -i upload.tar可以从upload.tar文件中加载镜像。

如果你觉得本文值得,不妨赏杯茶
没有上一篇
没有下一篇