testcontainers-python icon indicating copy to clipboard operation
testcontainers-python copied to clipboard

Feature: add DockerContainer.with_copy_file_to_container

Open Lenormju opened this issue 1 year ago • 6 comments

What are you trying to do?

Describe the intention of the enhancement.

I'd like to add a file to the container I'm starting, without using volumes.

Why should it be done this way?

Feature-parity with the Java version : https://java.testcontainers.org/features/files/#copying-files

Other references:

It you deem it interesting to implement, as I do, I can implement it.

Lenormju avatar Aug 05 '24 11:08 Lenormju

I have found this remark in a PR : https://github.com/testcontainers/testcontainers-python/pull/392#discussion_r1390988566 Indeed, this PR was not the right place to do it, but to implement it in a new one now would be perfect 😄

Lenormju avatar Aug 05 '24 11:08 Lenormju

In case anyone lands on this and wishes for copying (I use it to pass GCP creds to cloud sql proxy container, volume mount doesn't work on Linux), I use this rough workaround, the key point is to set restart policy on failure to allow it to fail as expected on missing creds file until the copy completes.

# Roughly based on proposed logic in https://github.com/testcontainers/testcontainers-python/pull/676/files
def copy_file_to_container(container: DockerContainer, host_path: str, container_path: str, mode: int):
    data = BytesIO()

    def set_mode(tarinfo: tarfile.TarInfo):
        tarinfo.mode = mode
        return tarinfo

    with tarfile.open(fileobj=data, mode='w') as tar:
        tar.add(host_path, arcname=container_path, filter=set_mode)

    data.seek(0)
    if not container._container.put_archive('/', data):
        raise Exception('Failed to copy file to container')

with (
        DockerContainer('gcr.io/cloud-sql-connectors/cloud-sql-proxy:2.14.3')
        .with_command(
            '--address 0.0.0.0 --health-check --http-address 0.0.0.0 foo'
        )
        .with_exposed_ports(5432, 9090)
        .with_env(environment_vars.CREDENTIALS, '/creds/creds.json')
        # Currently there is no way to copy a file before container starts, so we workaround by allowing the container
        # to restart on failure, which will stop when the copy has completed.
        # https://github.com/testcontainers/testcontainers-python/pull/676#discussion_r1934888327
        .with_kwargs(restart_policy={'Name': 'on-failure', 'MaximumRetryCount': 100})
    ) as container:
        copy_file_to_container(container, creds_path, '/creds/creds.json', 0o644)
        wait_for_logs(container, 'The proxy has started successfully and is ready for new connections!')

anuraaga avatar Jan 30 '25 01:01 anuraaga

From @anuraaga comment:

... the key point is to set restart policy on failure to allow it to fail as expected on missing creds file until the copy completes.

The need to restart the container I think is somewhat due to the fact that there is no way to directly create a container without also starting it, since our implementation of start calls docker_client.run. Ideally what you'd like to do here is:

docker container create docker cp docker start

but there's no direct way to do that here. You could potentially directly use the some methods in docker.client.containers to achieve the same as well

rhoban13 avatar Jun 16 '25 17:06 rhoban13

its a known bug, this library needs to start creating containers before starting them at some point

On Mon, Jun 16, 2025 at 1:54 PM Ryan Hoban @.***> wrote:

rhoban13 left a comment (testcontainers/testcontainers-python#665) https://github.com/testcontainers/testcontainers-python/issues/665#issuecomment-2977518176

From @anuraaga https://github.com/anuraaga comment:

... the key point is to set restart policy on failure to allow it to fail as expected on missing creds file until the copy completes.

The need to restart the container I think is somewhat due to the fact that there is no way to directly create a container without also starting it, since our implementation of start https://github.com/testcontainers/testcontainers-python/blob/main/core/testcontainers/core/container.py#L176 calls docker_client.run. Ideally what you'd like to do here is:

docker container create docker cp docker start

but there's no direct way to do that here. You could potentially directly use the some methods in docker.client.containers https://docker-py.readthedocs.io/en/stable/containers.html#module-docker.models.containers to achieve the same as well

— Reply to this email directly, view it on GitHub https://github.com/testcontainers/testcontainers-python/issues/665#issuecomment-2977518176, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACECGJFQRF7ERARHK7X2ICT3D4AG3AVCNFSM6AAAAABMAC4U3SVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDSNZXGUYTQMJXGY . You are receiving this because you are subscribed to this thread.Message ID: @.*** com>

alexanderankin avatar Jun 17 '25 14:06 alexanderankin

I haven't been following this repo much and assumed that post acquisition this repo was left to disappear. But actually it seems there are still releases so really surprised such fundamental issues still can't be fixed...

anuraaga avatar Jun 17 '25 14:06 anuraaga

The linked PR seems to be stalled with a really good point there we need to clarify the interface a bit before moving forward with it. Perhaps we should create a issue or draft PR with simply some tests clarifying that interface?

rhoban13 avatar Jun 17 '25 16:06 rhoban13