kagamihogeの日記

kagamihogeの日記です。

docker(WSL2) + Testcontainers

Testcontainersユニットテストの起動と終了と共にdockerコンテナも起動と終了してくれるライブラリ。windowsというかWSL2で動かすには若干の追加設定が必要だった。

背景

特に何も設定せずtestcontainersからWSLのdockerに接続しようとすると下記のようなエラーになる。これの解決にはホストからWSLのdockerへの通信設定が必要となる。

org.testcontainers.containers.ContainerFetchException: Can't get Docker image: RemoteDockerImage(imageName=gvenzl/oracle-xe:21.3.0-slim-faststart, imagePullPolicy=DefaultPullPolicy(), imageNameSubstitutor=org.testcontainers.utility.ImageNameSubstitutor$LogWrappedImageNameSubstitutor@64da2a7)

    at org.testcontainers.containers.GenericContainer.getDockerImageName(GenericContainer.java:1408)
    at org.springframework.boot.testcontainers.service.connection.ServiceConnectionContextCustomizerFactory.createSource(ServiceConnectionContextCustomizerFactory.java:77)
    (省略)
Caused by: java.lang.IllegalStateException: Could not find a valid Docker environment. Please see logs and check configuration
    at org.testcontainers.dockerclient.DockerClientProviderStrategy.lambda$getFirstValidStrategy$7(DockerClientProviderStrategy.java:276)
    at java.base/java.util.Optional.orElseThrow(Optional.java:403)
    at org.testcontainers.dockerclient.DockerClientProviderStrategy.getFirstValidStrategy(DockerClientProviderStrategy.java:267)
    at org.testcontainers.DockerClientFactory.getOrInitializeStrategy(DockerClientFactory.java:150)

手順 2024/6/7 追記

後述の旧手順で /etc/docker/daemon.json を修正すると以下のようなエラーでdockerが起動しなかった。なので手順を修正。

$ sudo systemctl restart docker.service
Job for docker.service failed because the control process exited with error code.
See "systemctl status docker.service" and "journalctl -xeu docker.service" for details.

環境

手順詳細

docker.service の設定を修正する。

$ sudo vim /lib/systemd/system/docker.service

#ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
ExecStart=/usr/bin/dockerd -H fd:// -H tcp://127.0.0.1:2375 -H unix:///var/run/docker.sock --containerd=/run/containerd/containerd.sock

本当は直接このファイルを修正するのは良くないらしくdrop-in ファイルというのを使用するみたいだが(無知故良く分かってない)、個人用のWSLをdockerのためだけに使うので妥協する。

サービスの再起動。

$ sudo systemctl daemon-reload
$ sudo systemctl restart docker.service

ホストのpowershellから疎通確認。以下のようにTcpTestSucceededがtrueになればOK。

> Test-NetConnection -ComputerName localhost -Port 2375
WARNING: TCP connect to (::1 : 2375) failed

ComputerName     : localhost
RemoteAddress    : 127.0.0.1
RemotePort       : 2375
InterfaceAlias   : Loopback Pseudo-Interface 1
SourceAddress    : 127.0.0.1
TcpTestSucceeded : True

次に、https://www.testcontainers.org/features/configuration/ にあるようにdocker.hostを修正する。C:/Users/myuser/.testcontainers.propertiesを以下のように修正する。

docker.host=tcp://localhost:2375

マニュアルによるとdocker.hostは以下三種類の指定方法があるとのことだが、自分の環境では3.のクラスパスは上手くいかなかった。なので2.のユーザホームに.testcontainers.properties(先頭に"."が必要なので注意)を置く方法にした。

1. Environment variables
2. .testcontainers.properties in user's home folder. Example locations:
  Linux: /home/myuser/.testcontainers.properties
  Windows: C:/Users/myuser/.testcontainers.properties
  macOS: /Users/myuser/.testcontainers.properties
3. testcontainers.properties on the classpath.

参考URL

手順(旧)

環境

手順詳細

まず、Docker Desktopを使わずにWSL2でVSCode Remote Containerを使う - Qiitaにあるようにtcpをlistenする。

/etc/docker/daemon.json

{
  "debug": false,
  "tls": false,
  "hosts": ["tcp://127.0.0.1:2375", "unix:///var/run/docker.sock"]
}

次に、https://www.testcontainers.org/features/configuration/ にあるようにdocker.hostを修正する。C:/Users/myuser/.testcontainers.propertiesを以下のように修正する。

docker.host=tcp://localhost:2375

マニュアルによるとdocker.hostは以下三種類の指定方法があるとのことだが、自分の環境では3.のクラスパスは上手くいかなかった。なので2.のユーザホームに.testcontainers.properties(先頭に"."が必要なので注意)を置く方法にした。

1. Environment variables
2. .testcontainers.properties in user's home folder. Example locations:
  Linux: /home/myuser/.testcontainers.properties
  Windows: C:/Users/myuser/.testcontainers.properties
  macOS: /Users/myuser/.testcontainers.properties
3. testcontainers.properties on the classpath.