-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a rootless Docker strategy #2985
Changes from 5 commits
00b6437
62cdd1a
e1d8f5a
0b13156
fb9c21e
5ae6ef6
dd7cc6f
53f5a42
5976196
72ad8d2
8dc8c79
f7f1a08
7ff171f
b9ffae3
cb01cc8
8b1e440
17f531f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
name: CI-Docker-Rootless | ||
|
||
on: | ||
pull_request: {} | ||
push: { branches: [ master ] } | ||
|
||
jobs: | ||
test: | ||
runs-on: ubuntu-18.04 | ||
steps: | ||
- uses: actions/checkout@v2 | ||
- name: debug | ||
run: id -u; whoami | ||
- name: uninstall rootful Docker | ||
run: sudo apt-get -q -y --purge remove moby-engine moby-buildx && sudo rm -rf /var/run/docker.sock | ||
- name: install rootless Docker | ||
run: curl -fsSL https://get.docker.com/rootless | sh | ||
- name: start rootless Docker | ||
run: PATH=$HOME/bin:$PATH XDG_RUNTIME_DIR=/tmp/docker-$(id -u) dockerd-rootless.sh --experimental --storage-driver vfs & | ||
- name: Build with Gradle | ||
run: XDG_RUNTIME_DIR=/tmp/docker-$(id -u) ./gradlew --no-daemon --scan testcontainers:test | ||
- name: aggregate test reports with ciMate | ||
if: always() | ||
continue-on-error: true | ||
env: | ||
CIMATE_PROJECT_ID: 2348n4vl | ||
CIMATE_CI_KEY: "CI / rootless Docker" | ||
run: | | ||
wget -q https://get.cimate.io/release/linux/cimate | ||
chmod +x cimate | ||
./cimate "**/TEST-*.xml" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package org.testcontainers.dockerclient; | ||
|
||
import com.sun.jna.Library; | ||
import com.sun.jna.Native; | ||
import org.apache.commons.lang.SystemUtils; | ||
|
||
import java.net.URI; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
import java.nio.file.Paths; | ||
|
||
/** | ||
* | ||
* @deprecated this class is used by the SPI and should not be used directly | ||
*/ | ||
@Deprecated | ||
public final class RootlessDockerClientProviderStrategy extends DockerClientProviderStrategy { | ||
|
||
public static final int PRIORITY = EnvironmentAndSystemPropertyClientProviderStrategy.PRIORITY + 20; | ||
|
||
private Path getSocketPath() { | ||
String xdgRuntimeDir = System.getenv("XDG_RUNTIME_DIR"); | ||
if (xdgRuntimeDir == null) { | ||
xdgRuntimeDir = "/run/user/" + LibC.INSTANCE.getuid(); | ||
} | ||
return Paths.get(xdgRuntimeDir).resolve("docker.sock"); | ||
} | ||
|
||
@Override | ||
public TransportConfig getTransportConfig() throws InvalidConfigurationException { | ||
return TransportConfig.builder() | ||
.dockerHost(URI.create("unix://" + getSocketPath().toString())) | ||
.build(); | ||
} | ||
|
||
@Override | ||
public String getDockerHostIpAddress() { | ||
return "localhost"; | ||
} | ||
|
||
@Override | ||
protected boolean isApplicable() { | ||
return SystemUtils.IS_OS_LINUX && Files.exists(getSocketPath()); | ||
} | ||
|
||
@Override | ||
public String getDescription() { | ||
return "Rootless Docker accessed via Unix socket (" + getSocketPath() + ")"; | ||
} | ||
|
||
@Override | ||
protected int getPriority() { | ||
return PRIORITY; | ||
} | ||
|
||
private interface LibC extends Library { | ||
|
||
LibC INSTANCE = Native.load("c", LibC.class); | ||
|
||
int getuid(); | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,13 +2,16 @@ | |
|
||
import com.github.dockerjava.api.DockerClient; | ||
import com.github.dockerjava.api.command.InspectContainerResponse.ContainerState; | ||
import com.github.dockerjava.api.model.Info; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.SneakyThrows; | ||
import lombok.experimental.FieldDefaults; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.apache.commons.io.FileUtils; | ||
import org.assertj.core.api.Assumptions; | ||
import org.junit.Test; | ||
import org.rnorth.ducttape.unreliables.Unreliables; | ||
import org.testcontainers.DockerClientFactory; | ||
import org.testcontainers.containers.startupcheck.StartupCheckStrategy; | ||
import org.testcontainers.containers.wait.strategy.AbstractWaitStrategy; | ||
|
||
|
@@ -21,6 +24,9 @@ public class GenericContainerTest { | |
|
||
@Test | ||
public void shouldReportOOMAfterWait() { | ||
Info info = DockerClientFactory.instance().client().infoCmd().exec(); | ||
// Poor man's rootless Docker detection :D | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 😂 for our tests, could we do this using the host socket URI? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I didn't want to do string matching, especially given that the feature is experimental and may change the socket location. Apparently, Docker returns There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Cool, I was wondering if that would be the case. Let's not hold up this PR for the change in docker-java, though - it's OK as-is. |
||
Assumptions.assumeThat(info.getDriver()).doesNotContain("vfs"); | ||
try ( | ||
GenericContainer container = new GenericContainer<>() | ||
.withStartupCheckStrategy(new NoopStartupCheckStrategy()) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want this to be the highest priority? I'd put this lower than
UnixSocketClientProviderStrategy
, at least after #1771 is merged (so thatDOCKER_HOST
is always respected, non-rootless-docker is tried first, and automatically configured rootless docker is tried last of all)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't want rootless DOCKER_HOST to take precedence (because we need to override the host ip) but yeah, I see what you mean.
I will make it have lower priority, but ensure that EnvAndSysPropsStrategy does not detect rootless host that easily
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
update:
with overridable host, it is no longer a problem when
EnvAndSysPropsStrategy
detects the rootlessDOCKER_HOST