🙆‍♀️

5年間修正されてないDockerfileをメンテする

2024/04/08に公開

前置き

大体こんな感じのDockerfileがありまして、

FROM ruby:2.5.1

WORKDIR /usr/src

RUN wget -qO- https://deb.nodesource.com/setup_12.x | bash -

RUN set -ex \
    && apt-get update \
    && apt-get install -y \
                nodejs \
                # for chrome packages
                fonts-liberation libappindicator3-1 libasound2 \
                libnspr4 libxtst6 libnss3 libxss1 xdg-utils lsb-release \
                --no-install-recommends

# seleniumを使ったテストを行うためにchromeをインストール
RUN curl -O https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb && \
    dpkg -i google-chrome-stable_current_amd64.deb

RUN npm install -g yarn

COPY Gemfile Gemfile.lock ./
RUN bundle install

最後にこのDockerfileがメンテナンスされたのが5年前でした。

debian9のリポジトリが移動されてる

まず、このdockerを立ち上げようとすると、apt-get updateがうまくいきません。
ruby:2.5.1で使用されているOSがdebian9(stretch)なのですが、すでにサポートが終了しており、パッケージ用のリポジトリのURLが変更されています。

これは、/etc/apt/sources.listをこんな感じで上書きすると解決します。

deb http://archive.debian.org/debian/ stretch contrib main
deb http://archive.debian.org/debian-security stretch/updates contrib main

chromeがインストールできない

自分のPCがm1 macだったので、amd64用のchromeはインストールできません。
5年前だと、m1 macもまだ販売してないです。たった5年でいろんなことが変わります。。。

また、先ほどのDockerfileにgoogle-chrome-stable_current_amd64.debと書いてあったところを_arm64に変えても、googleさんが用意してくれてないため、ダウンロードできません。

でもこれはFROM --platform=amd64 ruby:2.5.1に変えたとしても依存関係が解決できなくてエラーになります。

 > [web  6/10] RUN curl -O https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb &&      dpkg -i google-chrome-stable_current_amd64.deb:                                                                                                                
0.070   % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current                                                 
0.070                                  Dload  Upload   Total   Spent    Left  Speed                                                   
100  102M  100  102M    0     0  16.1M      0  0:00:06  0:00:06 --:--:-- 17.0M                                                        
6.508 Selecting previously unselected package google-chrome-stable.
6.522 (Reading database ... 41124 files and directories currently installed.)
6.522 Preparing to unpack google-chrome-stable_current_amd64.deb ...
6.529 Unpacking google-chrome-stable (123.0.6312.86-1) ...
13.08 dpkg: dependency problems prevent configuration of google-chrome-stable:
13.08  google-chrome-stable depends on libdrm2 (>= 2.4.75); however:
13.08   Version of libdrm2:amd64 on system is 2.4.74-1.
13.08  google-chrome-stable depends on libgbm1 (>= 17.1.0~rc2); however:
13.08   Version of libgbm1:amd64 on system is 13.0.6-1+b2.
13.08  google-chrome-stable depends on libnss3 (>= 2:3.35); however:
13.08   Version of libnss3:amd64 on system is 2:3.26.2-1.1+deb9u5.
13.08  google-chrome-stable depends on libu2f-udev; however:
13.08   Package libu2f-udev is not installed.
13.08  google-chrome-stable depends on libvulkan1; however:
13.08   Package libvulkan1 is not installed.
13.08 
13.08 dpkg: error processing package google-chrome-stable (--install):
13.08  dependency problems - leaving unconfigured
13.08 Processing triggers for mime-support (3.60) ...
13.18 Errors were encountered while processing:
13.18  google-chrome-stable

他のリポジトリ探せばこの依存関係は解決できるのか?までは調べきれず断念しました。

さらに、stableでなければいいのではないかと思い、古いchromeを探してみましたが、探すのが結構苦労する上、インストールできても、seleniumを使ったテストが、なぜか動かなかったです。。。

※古いのは↓から探すことができる
https://chromiumdash.appspot.com/

chrome専用のDockerを別で立てる

構成が少し複雑になり、capybara周りのコードも修正する必要がありますが、この方法ではうまく行きました。

docker-compose.ymlは↓みたいな感じでいけると思います。
https://github.com/na8esin/rails5-docker/blob/e302eaf34ed1d171a5284ef26a777cc018516ba8/docker-compose.yml#L30-L38

application_system_test_case.rbはこんな感じです。
※ちなみに、railsは5.2系です。

require "test_helper"

class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
  Capybara.register_driver :remote_chrome do |app|
    url = "http://chrome:4444/wd/hub"
    caps = ::Selenium::WebDriver::Remote::Capabilities.chrome(
      "goog:chromeOptions" => {
        "args" => [
          "no-sandbox",
          "headless",
          "disable-gpu",
          "window-size=1680,1050"
        ]
      }
    )
    Capybara::Selenium::Driver.new(app, browser: :remote, url: url, desired_capabilities: caps)
  end

  driven_by :remote_chrome

  def setup
    Capybara.server_host = IPSocket.getaddress(Socket.gethostname)
    Capybara.server_port = 4444
    Capybara.app_host = "http://web:#{Capybara.server_port}"

    super
  end
end

そして、テストはこんな感じです

test/system/book_test.rb
require "application_system_test_case"

class BookTest < ApplicationSystemTestCase

  test "visiting the index" do
    visit book_index_path

    take_screenshot

    assert_selector "h1", text: "Book#index"
  end
end

また、rspecでも書いてみました↓
https://github.com/na8esin/rails5-docker/tree/e302eaf34ed1d171a5284ef26a777cc018516ba8

おまけ

chromiumならインストールできるけど、実行できない

RUN apt-get install -y \
                chromium \
                chromium-driver \
                --no-install-recommends

pythonで簡単なスクリプトを書いてみても動かない

root@c7b3d4dbdb5a:/usr/src/app# python3 sample.py 
Traceback (most recent call last):
  File "sample.py", line 6, in <module>
    driver = webdriver.Chrome('/usr/bin/chromedriver')
  File "/usr/local/lib/python3.5/dist-packages/selenium/webdriver/chrome/webdriver.py", line 81, in __init__
    desired_capabilities=desired_capabilities)
  File "/usr/local/lib/python3.5/dist-packages/selenium/webdriver/remote/webdriver.py", line 157, in __init__
    self.start_session(capabilities, browser_profile)
  File "/usr/local/lib/python3.5/dist-packages/selenium/webdriver/remote/webdriver.py", line 252, in start_session
    response = self.execute(Command.NEW_SESSION, parameters)
  File "/usr/local/lib/python3.5/dist-packages/selenium/webdriver/remote/webdriver.py", line 321, in execute
    self.error_handler.check_response(response)
  File "/usr/local/lib/python3.5/dist-packages/selenium/webdriver/remote/errorhandler.py", line 242, in check_response
    raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.WebDriverException: Message: unknown error: Chrome failed to start: exited abnormally
  (unknown error: DevToolsActivePort file doesn't exist)
  (The process started from chrome location /usr/bin/chromium is no longer running, so ChromeDriver is assuming that Chrome has crashed.)
  (Driver info: chromedriver=73.0.3683.75,platform=Linux 6.5.13-orbstack-00122-g57b8027e2387 x86_64)
しくみのテックブログ

Discussion