心得

由于学校的服务器无法自行安装程序,不得不使用docker。到现在使用 docker 两年了,也颇有些心得: Docker 是基于 Linux 内核的,因此:

  • 有些 image 可以做到非常的小,只有几MB大。
  • 在 Windows 和 Mac 上用,以 Desktop for Mac 为例,实际上是先运行一个虚拟机,再在虚拟机上跑容器。因此,非常占用硬盘空间。
  • 做好 Dockerfile 优化,不要把 image 当成虚拟机用。

目前我是这样使用 docker 的。在 windows 电脑(有一块 4T 的硬盘)上装个 ubuntu 虚拟机,在里面使用 docker 构建 image,再把 image 推到 docker hub。然后在我学校的服务器上再拉下来用。

我使用的虚拟机软件是 VMware workstation 16。装好 unbuntu 之后,从 windows 里复制的文本,可以无缝粘贴到 ubuntu,很方便。

Desktop for Mac 占用硬盘空间问题

如图,在删除掉我不用的 image 和 container 之后,虽然显示只占了 14.27 GB的空间。
image.png
但是,如果你检查硬盘里的文件,会发现,docker 有一个文件依旧占据了近 90GB 的大小(如下图)。这个文件就是虚拟机文件,无论你怎么删除 image 和 container,这个文件都只增不减:

如果你删除 image 或 container,它不减少;
如果你新增 image 或 container,而且总大小超过它现在的大小了,那它就会增加。增加后就不会减少。
image.png
没有什么好方法压缩这个文件,看网友们的讨论,说是存在已久的 bug。只能删除它,重置整个 docker。但是这样做就会丢失里面的数据。所以在开发机上,不要在 docker 里存重要的数据。

什么是Docker?

Docker 说白了,就是一个方便部署应用的工具。

用于本机器开发当然也行,但是不利于调试。因为你的开发环境都在image里的话,IDE就没办法实现代码跳转之类的功能。

image.png

Docker的两个概念

Docker有两个概念,一个是 image,一个是containner。简单的说,image就是别人打包好的一个模板,你把它拉下来,实例化之后,就是containner。

使用流程

单从使用者的角度来说,使用 docker run [image name] 命令即可快速运行一个现成的image。

如果需要部署用户自己的代码,比如使用nginx部署一个静态站点。需要把代码放到container里执行。

这样的话,需要用到Dockerfile来build自己的image。

image.png

Dockerfile就是一个脚本文件,大致包含如下内容:

  • 指定使用哪个image
  • 创建一些目录
  • 在container里执行一些命令
  • 把站点代码复制到创建好的container里
  • 启动container时自动执行的命令

例如:

image.png

然后build & run。这样在浏览器就能看到效果了。

如果你的应用要用到多个container,那么使用 docker compose 工具可方便管理它们。

小结

  • Docker 适用于快速部署,不适合本机开发(写代码调试)用。
  • 工作原理就是先制作好某一工具(如nginx)的image,然后:pull image -> build 自己的 image -> run image。也就是说,每部署一次就要重新build一次。
  • 当然也能 docker 也能用于部署数据库工具,但是需要外挂一个数据盘以便持久化保存数据。

Build and Push image

  • Your Dockerfile will look something like this:

    1. FROM readytalk/nodejs
    2. # Add our configuration files and scripts
    3. WORKDIR /app
    4. ADD . /app
    5. RUN npm install
    6. EXPOSE 80
    7. ENTRYPOINT ["/nodejs/bin/npm", "start"]
  • Build your image by executing the docker build command. DOCKER_ACC is the name of your account $DOCKER_REPO is your image name and $IMG_TAG is your tag

docker build -t $DOCKER_ACC/$DOCKER_REPO:$IMG_TAG .

  • Now, you can push this image to your hub by executing the docker push command.

sudo docker push $DOCKER_ACC/$DOCKER_REPO:$IMG_TAG

  1. docker images
  2. docker run # 此命令具有自动pull image 文件的功能
  3. docker kill [containID] # 终止不会自动停止的容器
  4. docker rm [containerID] # 删除容器文件(终止运行的容器文件,依然会占据硬盘空间)
  5. docker run --rm # rm参数可在容器终止运行后自动删除容器文件
  6. docker build -t woffee/nlp:test .

image.png

image.png
image.png

Test:

  1. docker run -v /Users/woffee/www/docker/quase:/home -w /home -it woffee/quase:v1 python test.py
  2. # -v 把主机的目录挂载到容器的 /home 目录
  3. # -w 把容器的 /home 目录设置为工作目录

优化 Dockerfile,减少不必要的体积

Dockerfile 中,每一个 RUN 命令都会产生一个 layer,所以尽量把命令都写到一条语句中。

还可以采用分阶段构建法。其原理是,先在 A 里构建环境,再把 A 中构建好的文件(比如编译好的二进制文件)拷贝到 B 中,那么你最后的 image 就只包含必须的文件,体积也趋近于满足需求的条件下最小。

参考

http://blog.shippable.com/build-a-docker-image-and-push-it-to-docker-hub
http://www.ruanyifeng.com/blog/2018/02/docker-tutorial.html