5年間修正されてないDockerfileをメンテする
前置き
大体こんな感じの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を使ったテストが、なぜか動かなかったです。。。
※古いのは↓から探すことができる
chrome専用のDockerを別で立てる
構成が少し複雑になり、capybara周りのコードも修正する必要がありますが、この方法ではうまく行きました。
docker-compose.ymlは↓みたいな感じでいけると思います。
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
そして、テストはこんな感じです
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でも書いてみました↓
おまけ
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