LoginSignup
6

More than 3 years have passed since last update.

posted at

【Heroku】Railsのコンテナをpush時に「Error: docker push exited with Error: 1」

事象

下記のDockerfileおよびdocker-compose.yamlで作成したRailsのコンテナをHerokuにpushした際に

unknown blob
 ▸    Error: docker push exited with Error: 1

とエラーが発生しました。

Dockerfile
FROM ruby:2.6.3-stretch

RUN apt-get update &&\
    apt-get install -y nodejs build-essential libpq-dev postgresql-client

RUN mkdir /myapp
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
COPY . /myapp
docker-compose.yaml
version: "3"
services:
  db:
    image: postgres:11.4-alpine
    ports:
      - "5432:5432"
    volumes:
      - "./postgres-data:/var/lib/postgresql/data"
  web:
    build:
      context: .
      dockerfile: Dockerfile
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - ".:/myapp"
    ports:
      - "3000:3000"
    tty: true
    stdin_open: true
    depends_on:
      - db
    working_dir: "/myapp"

ちなみに、Herokuへのpushはローカルでコンテナの起動を停止後に下記の手順で行いました。

$ heroku create

$ heroku container:login

$ heroku container:push "コンテナ名"
↑このコマンドで上述のエラーが発生

原因と対策

エラーメッセージの「unknown blob Error: docker push exited with Error: 1」
を丸ごとコピペして検索すると、こちらのGitHubのissueを発見しました。

どうやら、コメントを読む限りでは、Herokuでコンテナを用いる際はCMDを用いる必要があるようです。

ただ、issueのコメントにあったこちらのリンクがCMDを用いる必要がある根拠なのかもしれませんが、私にはイマイチ読み取れませんでした。

あえて挙げるとすると

CMD will always be executed by a shell so that config vars are made available to your process; to execute single binaries or use images without a shell please use ENTRYPOINT`

CMDに関する記載なのですが、CMDが常にシェルによって実行されるからCMDを用いる必要があるということなんでしょうか...

いずれにせよ、一旦試しにDockerの公式サンプルを参考に下記のようにDockerfileを修正しました。

Dockerfile
FROM ruby:2.6.3-stretch

RUN apt-get update &&\
    apt-get install -y nodejs build-essential libpq-dev postgresql-client

RUN mkdir /myapp
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
COPY . /myapp

# ↓を追加
CMD ["rails", "server", "-b", "0.0.0.0"] 

Dockerfileを修正後に、再度pushしてみると、

・・・(省略)・・・
Your image has been successfully pushed.
You can now release it with the 'container:release' command.

とエラーメッセージが消え、pushに成功することができました。

CMDとは

ここで改めてCMDとはなんぞやということを調べてみましたら、非常に良い記事を発見したので、共有します。

@uehaj さんのDockerfileのCMDとENTRYPOINTを改めて解説するという記事です。

この記事によるとCMD指定には下記の2つの意味があるようです。

  1. docker runでコマンドを指定する方法において、「docker run」で実際のコマンドを何も指定しなかったときに実行するコマンド(と引数)のデフォルト値
  2. DockerfileのENTRYPOINT項目でコマンドを指定する方法において、ENTRYPOINTに指定したコマンドの追加的引数の、コマンドラインから指定しなかった場合のデフォルト値

結局CMDには2つ意味がありますが、

いずれの場合でも、CMDはrunの後に続ける引数のデフォルト値指定であると言える。

とのことです。

まとめ

コンテナをHerokuにpushした際に

unknown blob
 ▸    Error: docker push exited with Error: 1

とエラーが発生したら、DockerfileにCMDコマンドが書かれているかをチェックしてみると良いでしょう。

また、今回の調査の過程で、CMDは「docker runの後に続ける引数のデフォルト値を指定している」ということを学ぶことができました。改めてDockerの公式ドキュメントにも目を通しておこうと思います。

最後までお読みいただきありがとうございました。

参考文献

解決のきっかけ
https://github.com/heroku/cli/issues/1081

CMDを用いる必要がある根拠と思われるページ
https://devcenter.heroku.com/articles/container-registry-and-runtime#dockerfile-commands-and-runtime

DockerfileのCMDとENTRYPOINTを改めて解説する
https://qiita.com/uehaj/items/e6dd013e28593c26372d

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
6