Dokku:部署、构建和服务中间人静态生成的网站

Dokku: deploy, build & serve middleman statically generated website

今天,我一直在尝试配置Dokku来部署我的静态生成网站(使用中间人构建):将中间人源推送到主机,在主机上生成网站,并告诉nginx来提供那些静态文件。

根据这些资源 1 and 2,我设置了我的项目:

  1. 一个 .buildpacks 文件,包含一个用于构建站点的构建包,以及用于提供生成的静态 HTML 文件的 nginx 构建包:

    https://github.com/heroku/heroku-buildpack-ruby.git#v222
    https://github.com/dokku/buildpack-nginx.git#v14
    
  2. 一个 .static 文件,以便 nginx buildpack 知道它必须服务于静态网站

  3. 负责构建站点的预部署操作,使用 app.json :

    {
      "scripts": {
        "dokku": {
          "predeploy": "bundle exec middleman build",
        }
      }
    }
    

发生了什么事?

显然,目前我正在尝试使用预部署挂钩构建我的中间人站点,bundle 命令不再可用。这是我得到的示例输出:

➜ git push dokku master
Enumerating objects: 397, done.
Counting objects: 100% (397/397), done.
Delta compression using up to 8 threads
Compressing objects: 100% (258/258), done.
Writing objects: 100% (397/397), 819.50 KiB | 14.90 MiB/s, done.
Total 397 (delta 195), reused 244 (delta 111), pack-reused 0
remote: Resolving deltas: 100% (195/195), done.
-----> Cleaning up...
-----> Building site from herokuish...
-----> Adding BUILD_ENV to build environment...
-----> Warning: Multiple default buildpacks reported the ability to handle this app. The first buildpack in the list below will be used.
       Detected buildpacks: multi ruby static
-----> Multipack app detected
=====> Downloading Buildpack: https://github.com/heroku/heroku-buildpack-ruby.git
=====> Detected Framework: Ruby
-----> Installing bundler 2.1.4
-----> Removing BUNDLED WITH version in the Gemfile.lock
-----> Compiling Ruby/Rack
-----> Using Ruby version: ruby-2.6.3
-----> Installing dependencies using bundler 2.1.4
       Running: BUNDLE_WITHOUT='development:test' BUNDLE_PATH=vendor/bundle BUNDLE_BIN=vendor/bundle/bin BUNDLE_DEPLOYMENT=1 bundle install -j4
       Using concurrent-ruby 1.1.7
       Using i18n 0.9.5
       Using minitest 5.14.2
       Using thread_safe 0.3.6
       Using tzinfo 1.2.7
       Using activesupport 5.2.4.4
       Using public_suffix 4.0.6
       Using addressable 2.7.0
       Using execjs 2.7.0
       Using autoprefixer-rails 9.8.6.5
       Using backports 3.18.2
       Using bundler 2.1.4
       Using coffee-script-source 1.12.2
       Using coffee-script 2.4.1
       Using contracts 0.13.0
       Using dotenv 2.7.6
       Using erubis 2.7.0
       Using fast_blank 1.0.0
       Using fastimage 2.2.0
       Using ffi 1.13.1
       Using temple 0.8.2
       Using tilt 2.0.10
       Using haml 5.2.0
       Using hamster 3.0.0
       Using hashie 3.6.0
       Using rexml 3.2.4
       Using kramdown 2.3.0
       Using rb-fsevent 0.10.4
       Using rb-inotify 0.10.1
       Using listen 3.0.8
       Using memoist 0.16.2
       Using thor 1.0.1
       Using middleman-cli 4.3.11
       Using padrino-support 0.13.3.4
       Using padrino-helpers 0.13.3.4
       Using parallel 1.19.2
       Using rack 2.2.3
       Using sassc 2.4.0
       Using servolux 0.13.0
       Using uglifier 3.2.0
       Using middleman-core 4.3.11
       Using middleman 4.3.11
       Using middleman-autoprefixer 2.10.1
       Bundle complete! 3 Gemfile dependencies, 43 gems now installed.
       Gems in the groups development and test were not installed.
       Bundled gems are installed into `./vendor/bundle`
       Bundle completed (0.52s)
       Cleaning up the bundler cache.
-----> Writing config/database.yml to read from DATABASE_URL
-----> Installing node-v12.16.2-linux-x64
-----> Detecting rake tasks

       ###### WARNING:

       No Procfile detected, using the default web server.
       We recommend explicitly declaring how to boot your server process via a Procfile.
       https://devcenter.heroku.com/articles/ruby-default-web-server

=====> Downloading Buildpack: https://github.com/dokku/buildpack-nginx.git
=====> Detected Framework: .static
-----> Copy static files to www
-----> Reusing nginx binary from cache
-----> Using default app-nginx.conf.sigil
-----> Using default mime.types
       Using release configuration from last framework (.static).
-----> Discovering process types
       Default types for  -> web
-----> Releasing site...
-----> Deploying site...
-----> Checking for predeploy task
-----> Executing predeploy task from app.json: bundle exec middleman build
=====> Start of site predeploy task (22fcf68dd) output
remote:  !     Execution of predeploy task failed: bundle exec middleman build
       /bin/bash: bundle: command not found
remote: 2021/01/02 15:06:19 exit status 1
remote: 2021/01/02 15:06:19 exit status 1
remote: 2021/01/02 15:06:19 exit status 1
=====> End of site predeploy task (22fcf68dd) output
To host:site
 ! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to 'host:site'

我试过的

  1. 我注意到第一个 buildpack 被执行,然后是第二个,然后 predeploy 挂钩开始。

  2. 我尝试删除 nginx“静态服务”buildpack 并仅保留 ruby 一个,并在我的预部署挂钩中保留 bundle 命令。它有效,我没有收到“找不到命令”错误。所以切换到第二个 buildpack 似乎把事情搞砸了。

  3. 我比较了有和没有 nginx“静态服务”buildpack 的路径,没有什么奇怪的。使用 nginx buildpack,添加了一个新路径,但之前设置的 ruby 路径仍然存在:

    # with only ruby buildpack
    /app/bin:/app/vendor/bundle/bin:/app/vendor/bundle/ruby/2.6.0/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    
    # with both ruby & nginx buildpacks
    /app/bin:/app/vendor/bundle/bin:/app/vendor/bundle/ruby/2.6.0/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/app/nginx
    

最后,我在这里有点迷路了。是预期的吗?我不是在遵循 dokku 方式吗?我得到这个是因为权限问题,还是 Dokku 中我不知道的东西?

现在,作为后备,我通过 运行 接收所有请求的中间人服务器为网站提供服务,但是动态地为静态生成的网站提供服务是没有意义的。

感谢 jonrsharpe 的评论,我重新定位了我的搜索和 found this blog post on heroku engineering blog。最终,正如 jonrsharpe 所说:

The Nginx buildpack won't have Ruby in at all - you need to do any building in the Ruby buildpack context, so all the static buildpack needs to do is serve the results.

因此,要启动我的 middleman build 命令,我需要挂钩 ruby buildpack 中的某处。在“heroku 上的 jekyll”link 中,一切都得到了解释:应该覆盖 assets:precompile rake 任务

我遵循的步骤

  1. gem "rake" 添加到我的 Gemfile(当然还有捆绑包)
  2. 使用 assets:precompile 任务创建一个 Rakefile :
task "assets:precompile" do
  exec("middleman build")
end
  1. 尽情享受吧!