public Container.ExecResult execInContainer(
        DockerClient dockerClient,
        InspectContainerResponse containerInfo,
        Charset outputCharset,
        ExecConfig execConfig
    ) throws UnsupportedOperationException, IOException, InterruptedException {
        if (!TestEnvironment.dockerExecutionDriverSupportsExec()) {
            // at time of writing, this is the expected result in CircleCI.
            throw new UnsupportedOperationException(
                "Your docker daemon is running the \"lxc\" driver, which doesn't support \"docker exec\"."
            );
        }

        if (!isRunning(containerInfo)) {
            throw new IllegalStateException("execInContainer can only be used while the Container is running");
        }

        String containerId = containerInfo.getId();
        String containerName = containerInfo.getName();

        String[] command = execConfig.getCommand();
        log.debug("{}: Running \"exec\" command: {}", containerName, String.join(" ", command));
        final ExecCreateCmd execCreateCmd = dockerClient
            .execCreateCmd(containerId)
            .withAttachStdout(true)
            .withAttachStderr(true)
            .withCmd(command);

        String user = execConfig.getUser();
        if (user != null && !user.isEmpty()) {
            log.debug("{}: Running \"exec\" command with user: {}", containerName, user);
            execCreateCmd.withUser(user);
        }

        String workDir = execConfig.getWorkDir();
        if (workDir != null && !workDir.isEmpty()) {
            log.debug("{}: Running \"exec\" command inside workingDir: {}", containerName, workDir);
            execCreateCmd.withWorkingDir(workDir);
        }

        Map<String, String> envVars = execConfig.getEnvVars();
        if (envVars != null && !envVars.isEmpty()) {
            List<String> envVarList = envVars
                .entrySet()
                .stream()
                .map(e -> e.getKey() + "=" + e.getValue())
                .collect(Collectors.toList());
            execCreateCmd.withEnv(envVarList);
        }

        final ExecCreateCmdResponse execCreateCmdResponse = execCreateCmd.exec();

        final ToStringConsumer stdoutConsumer = new ToStringConsumer();
        final ToStringConsumer stderrConsumer = new ToStringConsumer();

        try (FrameConsumerResultCallback callback = new FrameConsumerResultCallback()) {
            callback.addConsumer(OutputFrame.OutputType.STDOUT, stdoutConsumer);
            callback.addConsumer(OutputFrame.OutputType.STDERR, stderrConsumer);

            dockerClient.execStartCmd(execCreateCmdResponse.getId()).exec(callback).awaitCompletion();
        }
        int exitCode = dockerClient.inspectExecCmd(execCreateCmdResponse.getId()).exec().getExitCodeLong().intValue();

        final Container.ExecResult result = new Container.ExecResult(
            exitCode,
            stdoutConsumer.toString(outputCharset),
            stderrConsumer.toString(outputCharset)
        );

        log.trace("{}: stdout: {}", containerName, result.getStdout());
        log.trace("{}: stderr: {}", containerName, result.getStderr());
        return result;
    }
Run a command inside a running container as a given user, as using "docker exec -u user".
<p>
This functionality is not available on a docker daemon running the older "lxc" execution
driver. At the time of writing, CircleCI was using this driver.
@param dockerClient the {@link DockerClient}
@param containerInfo the container info
@param outputCharset the character set used to interpret the output.
@param execConfig the exec configuration
@return the result of execution
@throws IOException if there's an issue communicating with Docker
@throws InterruptedException if the thread waiting for the response is interrupted
@throws UnsupportedOperationException if the docker daemon you're connecting to doesn't support "exec".
core/src/main/java/org/testcontainers/containers/ExecInContainerPattern.java