GeekNote
注册
登录

Rails on Docker: 用 docker-sync 改善文件同步性能

Rei

💡 Rails on Docker 系列文章是面向 Rails 程序员的 Docker 教程,描述了如何从开发环境到部署环境中应用 Docker。这是系列文章的第三篇。

上一节中我们已经学习了用 Docker Compose 搭建开发环境,这一节将介绍如何用 docker-sync 改善开发环境的文件同步性能。

文件同步有什么问题?

在 Mac 下使用 Docker,你可能会发现性能差得离谱。一个在本地环境 2 秒启动的 Rails 应用,在容器里面要一分钟。如果项目依赖很多(例如 NPM),速度会慢得让你怀疑是不是已经死机。

性能低下的原因是文件同步太慢,这是 Docker for Mac 一个由来已久的问题(issue。Docker for Mac 内置的文件同步机制是 OSXFS,由于涉及文件系统转换,同步过程相当耗时,文件稍微多一些时就会明显拖慢性能。

Docker 4.6 版本引入了新的文件同步机制,据说大大提升了同步性能。在我测试中,新的同步机制虽然有了改善,但还是比理想情况慢了很多。一个不严谨的比较是:

旧同步机制(50s) > 新同步机制(10s)> docker-sync(2s)> 本地性能(1s)

所以如果你使用了新同步机制下还觉的慢,那么推荐使用 docker-sync。

docker-sync 简介

docker-sync 是一个命令行工具,用于替代 Docker Desktop 内置的文件同步机制,解决性能问题。

docker-sync 的原理可以看下图:

native_osx.png

docker-sync 把同步机制分成了两步,第一步是通过 OSXFS 同步本地文件和虚拟机中的目录,第二步是将虚拟机的目录和要挂载的 volume 同步。最终挂载到 app 的 volume 是一个虚拟机的内部目录,避免直接调用 OSXFS,从而提高性能。详细的同步机制可以看 docker-sync 的文档

使用 docker-sync 之后,虽然同步会有延迟(约 1 秒),但是应用执行速度很快,能满足开发的需要。

docker-sync 使用

首先安装 docker-sync 工具,它是一个 gem 包:

$ gem install docker-sync

在项目目录下创建文件 docker-sync.yml,内容如下:

version: "2"
syncs:
  # 卷名,通常是 AppName-sync
  myapp-sync:
    src: './app'
    # 可以添加其他需要忽略的目录
    sync_excludes: ['.git', 'tmp', 'log']

修改 docker-compose.yml 文件中的 volume 设置:

version: "3.9"

services:
  web:
    build: .
    command: bin/rails server -b 0.0.0.0
    volumes:
      # 使用命名 volume,:nocopy 标记是必须的
      - myapp-sync:/app:nocopy
    ports:
      - 3000:3000
    depends_on:
      - postgres
  postgres:
    image: postgres:13
    environment:
      POSTGRES_PASSWORD: postgres

# volumne 指向 docker-sync 维护的卷
volumes:
  myapp-sync:
    external: true

然后用下面命令启动开发环境:

$ docker-sync start
$ docker compose up

如果一切正常,我们会看到 docker compose 环境启动,并且应用性能会大幅提升。

更多 docker-sync 的设置,可以查看它的官方文档

总结

通过引入 docker-sync,我们解决了 docker compose 在开发环境的一个痛点。不过每增加一个工具就增加一点复杂,希望 docker 本身的同步机制能继续优化,有一天可以抛弃 docker-sync。

下一节将会讲述 docker 在生产环境的应用。

3
Ruby 程序员,Ruby China 管理员,Gee...
登录后评论
评论 3

没用docker-sync
Completed 200 OK in 278ms (Views: 267.4ms | ActiveRecord: 7.1ms | Allocations: 16308)

使用docker-sync后,
Completed 200 OK in 61ms (Views: 28.3ms | ActiveRecord: 2.8ms | Allocations: 17936)

进步非常明显

当然macOS上直接运行,速度更快。
Completed 200 OK in 21ms (Views: 18.5ms | ActiveRecord: 1.1ms | Allocations: 11140)

但是各种项目依赖不好管理,所以还是用docker。

reply
回复

我写这系列文章的一个目的是别人要我解释的时候我可以发链接过去~

k8s 我已经放弃了,不是小项目应该用的;大项目有专门运维团队,也不用开发处理。

小项目部署可以用 docker swarm,理念和使用相对简单很多。

或者使用 PaaS,例如 fly.io 。

reply
回复

Rei 上次在推上看到了你用我留言的内容来说明留言区折叠问题,哈哈哈。
后来我自己捣鼓到了k8s,很酷。但是发现k8s需要学习的成本太高了...
你的docker系列我还是会持续关注的,加油。虽然看的人很少... 这太尴尬了

社区准则 博客 联系 反馈 状态
主题