private void runWithCompose(String cmd) { final DockerCompose dockerCompose; if (localCompose) { dockerCompose = new LocalDockerCompose(composeFiles, project); } else { dockerCompose = new ContainerisedDockerCompose(composeFiles, project); } dockerCompose .withCommand(cmd) .withEnv(env) .invoke(); }
public ContainerisedDockerCompose(List<File> composeFiles, String identifier) { super(TestcontainersConfiguration.getInstance().getDockerComposeContainerImage()); validateFileList(composeFiles); addEnv(ENV_PROJECT_NAME, identifier); // Map the docker compose file into the container final File dockerComposeBaseFile = composeFiles.get(0); final String pwd = dockerComposeBaseFile.getAbsoluteFile().getParentFile().getAbsolutePath(); final String containerPwd = MountableFile.forHostPath(pwd).getFilesystemPath(); final List<String> absoluteDockerComposeFiles = composeFiles.stream() .map(File::getAbsolutePath) .map(MountableFile::forHostPath) .map(MountableFile::getFilesystemPath) .collect(toList()); final String composeFileEnvVariableValue = Joiner.on(UNIX_PATH_SEPERATOR).join(absoluteDockerComposeFiles); // we always need the UNIX path separator logger().debug("Set env COMPOSE_FILE={}", composeFileEnvVariableValue); addEnv(ENV_COMPOSE_FILE, composeFileEnvVariableValue); addFileSystemBind(pwd, containerPwd, READ_ONLY); // Ensure that compose can access docker. Since the container is assumed to be running on the same machine // as the docker daemon, just mapping the docker control socket is OK. // As there seems to be a problem with mapping to the /var/run directory in certain environments (e.g. CircleCI) // we map the socket file outside of /var/run, as just /docker.sock addFileSystemBind(getDockerSocketHostPath(), "/docker.sock", READ_WRITE); addEnv("DOCKER_HOST", "unix:///docker.sock"); setStartupCheckStrategy(new IndefiniteWaitOneShotStartupCheckStrategy()); setWorkingDirectory(containerPwd); String dockerConfigPath = determineDockerConfigPath(); if (dockerConfigPath != null && !dockerConfigPath.isEmpty()) { addFileSystemBind(dockerConfigPath, DOCKER_CONFIG_FILE, READ_ONLY); } }
@Override public void invoke() { super.start(); this.followOutput(new Slf4jLogConsumer(logger())); // wait for the compose container to stop, which should only happen after it has spawned all the service containers logger().info("Docker Compose container is running for command: {}", Joiner.on(" ").join(this.getCommandParts())); while (this.isRunning()) { logger().trace("Compose container is still running"); Uninterruptibles.sleepUninterruptibly(100, TimeUnit.MILLISECONDS); } logger().info("Docker Compose has finished running"); AuditLogger.doComposeLog(this.getCommandParts(), this.getEnv()); final Integer exitCode = this.dockerClient.inspectContainerCmd(containerId) .exec() .getState() .getExitCode(); if (exitCode == null || exitCode != 0) { throw new ContainerLaunchException( "Containerised Docker Compose exited abnormally with code " + exitCode + " whilst running command: " + StringUtils.join(this.getCommandParts(), ' ')); } } }
public ContainerisedDockerCompose(List<File> composeFiles, String identifier) { super(TestcontainersConfiguration.getInstance().getDockerComposeContainerImage()); validateFileList(composeFiles); addEnv(ENV_PROJECT_NAME, identifier); // Map the docker compose file into the container final File dockerComposeBaseFile = composeFiles.get(0); final String pwd = dockerComposeBaseFile.getAbsoluteFile().getParentFile().getAbsolutePath(); final String containerPwd = MountableFile.forHostPath(pwd).getFilesystemPath(); final List<String> absoluteDockerComposeFiles = composeFiles.stream().map(File::getAbsolutePath).map(MountableFile::forHostPath).map(MountableFile::getFilesystemPath).collect(toList()); final String composeFileEnvVariableValue = Joiner.on(UNIX_PATH_SEPERATOR).join(absoluteDockerComposeFiles); // we always need the UNIX path separator logger().debug("Set env COMPOSE_FILE={}", composeFileEnvVariableValue); addEnv(ENV_COMPOSE_FILE, composeFileEnvVariableValue); addFileSystemBind(pwd, containerPwd, READ_ONLY); // Ensure that compose can access docker. Since the container is assumed to be running on the same machine // as the docker daemon, just mapping the docker control socket is OK. // As there seems to be a problem with mapping to the /var/run directory in certain environments (e.g. CircleCI) // we map the socket file outside of /var/run, as just /docker.sock addFileSystemBind(getDockerSocketHostPath(), "/docker.sock", READ_WRITE); addEnv("DOCKER_HOST", "unix:///docker.sock"); setStartupCheckStrategy(new IndefiniteWaitOneShotStartupCheckStrategy()); setWorkingDirectory(containerPwd); String dockerConfigPath = determineDockerConfigPath(); if (dockerConfigPath != null && !dockerConfigPath.isEmpty()) { addFileSystemBind(dockerConfigPath, DOCKER_CONFIG_FILE, READ_ONLY); } }
@Override public void invoke() { super.start(); this.followOutput(new Slf4jLogConsumer(logger())); // wait for the compose container to stop, which should only happen after it has spawned all the service containers logger().info("Docker Compose container is running for command: {}", Joiner.on(" ").join(this.getCommandParts())); while (this.isRunning()) { logger().trace("Compose container is still running"); Uninterruptibles.sleepUninterruptibly(100, TimeUnit.MILLISECONDS); } logger().info("Docker Compose has finished running"); AuditLogger.doComposeLog(this.getCommandParts(), this.getEnv()); final Integer exitCode = this.dockerClient.inspectContainerCmd(containerId).exec().getState().getExitCode(); if (exitCode == null || exitCode != 0) { throw new ContainerLaunchException("Containerised Docker Compose exited abnormally with code " + exitCode + " whilst running command: " + StringUtils.join(this.getCommandParts(), ' ')); } } }
private void runWithCompose(String cmd) { final DockerCompose dockerCompose; if (localCompose) { dockerCompose = new LocalDockerCompose(composeFiles, project); } else { dockerCompose = new ContainerisedDockerCompose(composeFiles, project); } dockerCompose.withCommand(cmd).withEnv(env).invoke(); }