#Sequencing Container Execution

1 messages · Page 1 of 1 (latest)

slow hazel
#

TLDR: Is there a proper way to ensure short-running containers are executed in the correct order at runtime?

Hi, in our current setup, we have distinct containers that:

Container 1: Database (long-running, exposed port)
Container 2: Apply migrations (short running code/script, no exposed port, published container)
Container 3: Seeds the database programmatically (short running code/script, no exposed port, published container)
Container 4: Run the API (long-running, exposed port, published container)
Container 5. Run the integration tests ("short" running executable, not a service).

If I was to describe the DAG it would look something like this (ctr, ctr/serviceBinding):

((5, 4), (4, 3), (3, 2), (2, 1), (5, 1), (4,1))

It's easy enough to specify the service dependency (WithServiceBinding) from DB (ctr 1) <- API (ctr 4) <- Integration(ctr 5). So we needed to apply migration (ctr 2) and seed data (ctr 3), but I am not sure what is the clean way to do so (other than executing the code in the same container at runtime).

#

Making them (migration and seed) services with no exposed port does work the first time, but on subsequent runs, they get cached and not executed. So the database is effectively empty on subsequent runs and integration tests fail. Using an env var to bust the cache ensures that the integration tests run never get cached. Also, since there is no port to wait on, the API (ctr 4) and integration tests (ctr 5) could technically start before the migration and seeding have been completed.

So far, I have worked around the migration code by injecting the migrations in the database container works. The issue is that for the seeding (ctr 3) I would need to copy it in the API (ctr 4) and execute it when before the service start (e.g.: WithExec([]string{"sh", "-c", "/srv/seed && /srv/api"})).

Another workaround would be to make those short-lived script/binary containers expose a port and only
WithExposedPort(8080).WithExec([]string{"sh", "-c", "/srv/seed && while true; do { echo -e 'HTTP/1.1 200 OK\r\n'; sh test; } | nc -l 8080; done"}) That would imply adding netcat as a dependency to our images, would be a bit silly.

Ultimately, I am looking for a way to define short-lived runtime dependencies that must be run before the actual container. WithServiceBinding seems almost there, but not quite.

To reiterate, Is there a proper way to ensure short-running containers are executed in the correct order?

austere viper
#

Hey @slow hazel! I'm not entirely sure if this would work as expected. But you could leverage the Sync function to force the evaluation of a dag at some point in time. Based on the list dag you shared above, it would be something like this:

  1. Create DB Service
  2. Create migrations container, ServiceBind to the database and run Sync on it
  3. Create seeds container, ServiceBind to the database and run Sync on it
  4. Create API container, Service bind to the database
  5. Create integrations container, service bind to the API and run it

What makes me doubt if this works or not is how the service references work. I'm not sure if by performing a Sync in two separate cases, there are new instances of the database service started on each one. I don't think that is how it works, but I would have to test to make sure. If you can make those change great, if not I'll be able to test this later in the afternoon! party_gopher

slow hazel
#

Hey @austere viper that was actually my initial approach (described above). I should have mentioned it used Sync(ctx). As mentioned, on subsequent runs, Dagger sees them as CACHED, so the code is never running on subsequent runs. Trying to bust the cache explicitly (e.g. an env var CACHEBUSTER=$(date +%s)) would invalidate the cache of anything that depends on these containers (ctr 2 and 3).

#

I guess if there was a .ForceSync(ctx) method that would ignore the last WithExec that would do it. Alternatively a WithExecAlways (or a better name). Since the output would be the same so it would not bust the cache. 🤷‍♂️