LoginSignup
1
0

More than 1 year has passed since last update.

Dockerのruby:2.7-alpineでruby2.7がないといわれてしまう

Last updated at Posted at 2021-01-24

はじめに

これまでいくつかのDockerimageを構築してきました。OpenAPIとSinatraの組み合わせは、お手軽なのですが、これまで作成してきたイメージを作り直したところ問題が発生しました。

Dockerでbundle exec rackup ...を実行したタイミングでエラーメッセージが表示されてしまうようになりました。

エラーメッセージ
$ sudo docker run -it --rm  \
        --env LC_CTYPE=ja_JP.UTF-8 \
        --env RACK_ENV="deployment" \
        -p 8080:8080 \
        --name webapp mywebapp \
...
+ bundle exec rackup --host 0.0.0.0 --port 8080
env: can't execute 'ruby2.7': No such file or directory

コンテナ内のファイルを確認して、最後のメッセージは ./lib/ruby/2.7.0/bin/rackupコマンドがruby2.7を呼び出しているからということは分かりました。

Dockerfileは次のようになっていて、multi-stage buildを利用しています。

Dockerfileの抜粋
FROM ruby:2.7-alpine as rubydev

RUN apk update && \
        apk add --no-cache tzdata bash ca-certificates make gcc libc-dev

COPY . /app
WORKDIR /app
RUN bundle config path lib
RUN bundle install

FROM ruby:2.7-alpine

RUN apk update && \
        apk add --no-cache tzdata bash ca-certificates

COPY --from=rubydev /app /app
WORKDIR /app

ADD run.sh /run.sh
RUN chmod +x /run.sh

RUN addgroup sinatra
RUN adduser -S -G sinatra sinatra
USER sinatra
RUN bundle config path lib ## generating the ~/.bundle/config file.

ENTRYPOINT ["/run.sh"]

理由

rackupを探してみると、2箇所に存在していて、なぜか lib/ruby/2.7.0/bin/rackup では ruby2.7バイナリを探していました。

+ find lib/ -name rackup
lib/ruby/2.7.0/bin/rackup
lib/ruby/2.7.0/gems/rack-2.2.3/bin/rackup
+ cat lib/ruby/2.7.0/bin/rackup
#!/usr/bin/env ruby2.7
...
+ cat lib/ruby/2.7.0/gems/rack-2.2.3/bin/rackup
#!/usr/bin/env ruby
...

ワークアラウンドで対応するのであれば、/usr/local/bin/ruby2.7 を準備する方法もあります。

Dockefileに追加した1行
RUN ln -s ruby /usr/local/bin/ruby2.7

ただ、こういった現象が発生するはずがないと思っていたので、少し原因の調査を進めました。

原因

結論からいうと、問題は Dockerfile の次の箇所にありました。

問題のあったDockerfileの抜粋
COPY . /app

ここではDockerfileを含めて全てのファイルをコピーしています。
Dockerfile自体は秘密ではないため、この方法自体は横着しているなという程度のものですが、問題はこの時点でカレントディレクトリの./lib/ruby/2.7.0/ ディレクトリもコピーされてしまったことでした。

コンテナを作成する前にコードをデバッグする目的で、ローカルのUbuntu環境でもrackupを起動しています。
そのため、bundle install コマンドを実行することで、./lib/ruby/2.7.0/bin/rackup が配置されていたのでした。

Ubuntuでは /usr/bin/ruby が ruby2.7へのシンボリックリンクとなっているため、このrackupはruby2.7から起動されるようになっていました。

Ubuntuに配置されたrackupコマンド
$ head -2 ./lib/ruby/2.7.0/bin/rackup
#!/usr/bin/env ruby2.7
#

他のDockerfileを処理するMakefileの中で、./lib/ruby ディレクトリを削除していたのですが、このイメージを作成する作業用リポジトリのMakefileには、このコードが含まれていませんでした。

Makefileのdockerイメージをbuildする箇所の処理抜粋
## local debug用のコマンド
bundle-install:
        bundle install --path lib

## dockerイメージをbuild
docker-build:
        rm Gemfile.lock || true
        sudo docker build . --tag $(DOCKER_IMAGE)

Gemfile.lockファイル以外に、./lib/ruby/, ./.bundle/ ディレクトリを削除するコードを追加することで恒久的な対策となりました。

必要な変更を加えた後のMakefileの例
NAME = sinatra-webapp
DOCKER_IMAGE = sinatra-webapp
DOCKER_IMAGE_VERSION = 0.1.1
IMAGE_NAME = $(DOCKER_IMAGE)
REGISTRY_SERVER = docker.io
REGISTRY_LIBRARY = please-overwrite-by-your-docker-id

docker-build:
        rm -f Gemfile.lock
        rm -fr lib/ruby
        rm -fr .bundle
        sudo docker build . --tag $(IMAGE_NAME)

docker-build-prod:
        rm -f Gemfile.lock
        rm -fr lib/ruby
        rm -fr .bundle
        sudo docker build . --tag $(IMAGE_NAME):$(DOCKER_IMAGE_VERSION) --no-cache

docker-tag:
        sudo docker tag  $(IMAGE_NAME):$(DOCKER_IMAGE_VERSION) $(REGISTRY_SERVER)/$(REGISTRY_LIBRARY)/$(IMAGE_NAME):$(DOCKER_IMAGE_VERSION)

docker-push:
        sudo docker push $(REGISTRY_SERVER)/$(REGISTRY_LIBRARY)/$(IMAGE_NAME):$(DOCKER_IMAGE_VERSION)

上記のMakefileはGitHubで公開しているdocker-sccp-sinatra-sampleに含まれる _docker/Makefile からの抜粋です。

結果は勘違いから勝手に悩んでいるだけだったのですが、手持ちのコンテナをbuildするプロセスを再度チェックしました。他のイメージでは ./.bundle/ や、./lib/ruby を削除していたので、思い込みがあったこともあって、解決がすぐに出来ませんでした。

現在はテンプレートを準備しているので、基本的には同じような問題は発生していません。

以上

1
0
0

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
  3. You can use dark theme
What you can do with signing up
1
0