Skip to content
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

feat(core): Extend container support #559

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

Tranquility2
Copy link
Contributor

@Tranquility2 Tranquility2 commented Apr 28, 2024

Overview

So basically as you can see from the title this adds a functionally that I think is super useful, supporting working with Dockerfile for achieving even more compatibility with custom images.

from testcontainers.core.container import DockerContainer
from testcontainers.core.image import DockerImage

with DockerImage(path=".", tag="new_image") as image  # tag is optional
    with DockerContainer(image=image.name) as container:
        ...

The created image is cleaned and any any intermediate containers are removed.

Background

I'm a bit biased as I originally started from working on my own project: https://github.com/Tranquility2/dockerr that has some very clear similarities with testcontainers.
I noticed testcontainers in Go and Java (for example) indeed support Dockerfile (and even some extra compatibility modes like Dockerfile DSL) so decided to take the time and add this to testcontainers-python as well.

Goal

The end goal will be supporting custom images that can be tested, in my use case:

  1. FastAPI / Flask
  2. Amazon Lambdas (using the built-in runtime interface emulator

Work Plan

This is what I'm planning to do

  • Add this PR to support the core image
  • Improve custom image support but easier usage, for example:
from testcontainers.core.generic import CustomContainer

with CustomContainer(tag="my-custom-image:latest", path="/path/to/Dockerfile") as server: # tag is optional
    server_url = custom_container.get_url()
  • Add some support for get_api to get the full user experience
  • Add Module for FastAPI
  • Add Module for Amazon Lambda

Future work

  • Add custom image support for more capabilities like the Dockerfile DSL

Any feedback is welcomed and I'll be happy to update/fix as needed.

Update
Took me some time but I did found #83 which is quite old and #455 which takes a different approach from what I have here.

Update 2 - Please note this proposal emphasize on 2 things

  1. Cleanup as much as possible
  2. Minimal changes to the current workflow. DockerContainer basically remains the same, this limits maintenance required and allows for easier integration.

Update 3 - Hopefully done ,this PR includes multiple feats

  • Image build support (using Dockerfile)
  • Added SrvContainer
  • Added FastAPI module
  • Added AWS Lambda module

@Tranquility2 Tranquility2 force-pushed the image_build branch 2 times, most recently from 00bd819 to 27dfc5a Compare May 6, 2024 17:13
Comment on lines +60 to +78
def __exit__(self, exc_type, exc_val, exc_tb) -> None:
self.remove()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rather than untagging - why not never tag and let it be cleaned up by system prune? im just thinking aloud - not 100% confident about how it works in java but the other pr for custom image also does what you did here, just challenging yall to think of something without the tagging/removal issue.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me try and follow up on this notion (sorry for the wall of text)

let me start with saying I do think its possible, the tag in the image is not mandatory, and if kept as a ref to the image object we can probably use the id to be passed as the image to DockerContainer, this will have a very different workflow from what I presented in this commit as we don't really need a context manager. now having established this:

TL;DR
I think the tagging can be changed to be optional (need to do some testing) and the removal is not an issue but a very important feature (implemented and included on the java version) which can be optional (defaults to true)

@Tranquility2
Copy link
Contributor Author

Image creation is now based on id as advised by @alexanderankin (tag is optional and not critical to the build flow)

@Tranquility2
Copy link
Contributor Author

Image cleanup is now optional (defaults to True to facilitate the use-cases known to me)

@Tranquility2
Copy link
Contributor Author

Please note that test_core.py now take double the time (~15sec on my machine)

@Tranquility2 Tranquility2 changed the title Add support for building custom image from Dockerfile feat(core): support custom image build (using Dockerfile) May 11, 2024
@Tranquility2 Tranquility2 changed the title feat(core): support custom image build (using Dockerfile) feat(core): support image build (using Dockerfile) May 11, 2024
@alexanderankin
Copy link
Collaborator

for fast api, i can imagine the plan is to create a Testcontainer for an intree service to test against from other intree services' test suites. what is the plan for aws lambda exactly?

@Tranquility2
Copy link
Contributor Author

Tranquility2 commented May 12, 2024

I think its basically extending the paradigm for testcontainers-python.
Instead of only providing the supporting services for testing something, one can now test a service ("dockerized" one).
I updated the doctest for SrvContainer (and code ofc) to better reflect this, so I hope it will be more clear, any python web service could benefit from testing it like this + we can provide supported services as neeed, for example:

with RedisContainer() as redis_container:
    redis_params = redis_container.get_client_params()
    with FastAPIContainer() as server: # this is very close to SrvContainer
        # do some calls to the server and utilize the fact that its connected to redis

*at this point I'm not as sure we will need a module for FastAPI but still needs to think about it

Now regarding aws lambda its very similar to the localstack module already available, and very ironically will probably also be used with it quite a lot. if we look at an example:

with LocalStackContainer() as localstack:
    dynamo_client = localstack.get_client("dynamodb")
    # prepare something in dynamo
    with AwsLambdaContainer() as lambda:
        # run some requests to http://localhost:9000/2015-03-31/functions/function/invocations
        # this way we can be validating flow with dynamo 
        # and maybe even checking the changes on dynamo itself

*this is static URL in all AWS lambdas
**AwsLambdaContainer will be a new module
***similar=have all the same env vars, as its all AWS eco system

@Tranquility2
Copy link
Contributor Author

Decided to implement a module for FastAPI, I think it will be good even on a didactic level for anyone who needs to use it, as it include a working example and all the sources.

@Tranquility2 Tranquility2 changed the title feat(core): support image build (using Dockerfile) feat(core): Image build support (using Dockerfile) May 14, 2024
Added DockerImage to core

Make sure all build related stuff are removed after

Fix Image related issues

Improve image removal code

Add test from docker client kwargs image

Added core test from image flow

Improve docstring for Image

Update core Readme to include image and full example

Update core Readme to include image and full example

Fix usage of image name

Update test from image string

Replace image name with tag

Update image remove handling

Fix image usage doctest
Added doctest to CustomContainer and update readme

Fix issue with CustomContainer image handle

Add test for CustomContainer

Update image var on CustomContainer

Image build based on id

Image clean is now optional

Fixed doctest

Update log about image removal

Improve image related test flow

Refactor CustomContainer into SrvContainer

Refactor image related test flow

Improve SrvContainer

Fix test_srv_container logs check

Improve SrvContainer and update tests

Updates for SrvContainer
Fix missing doc in index

Fix extra

Fix missing httpx as optional dependency
@Tranquility2 Tranquility2 force-pushed the image_build branch 2 times, most recently from f4490c2 to 5088097 Compare May 15, 2024 17:48
@Tranquility2
Copy link
Contributor Author

  1. Added Module for Amazon Lambda
  2. Reorganized the PR commits:
feat(core): Added AWS Lambda module
feat(core): Added FastAPI module
feat(core): Added SrvContainer
feat(core): Image build support (using Dockerfile)

They now reflect better the improvements and the work that was done.

@Tranquility2 Tranquility2 changed the title feat(core): Image build support (using Dockerfile) feat(core): Extend container support May 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants