#Running containers locally / re-inventing the wheel? ๐Ÿ›ž

1 messages ยท Page 1 of 1 (latest)

upbeat raven
#

I made myself these utility functions for building & running a container locally. Mosty for testing containers before sending them to remote registery. Am I duplicating some dagger functionality? Can this be simplified?

async function runLocally() {
  withDaggerClient(async client => {
    const container = createContainer(client); // this runs several withExecs withDirectories etc eventually adds a withEntryPoint
    const containerPath = await buildContainer({ runner: container });
    console.log('containerPath', containerPath);
    const imageId = await loadContainer({ path: containerPath });
    console.log('imageId', imageId);
    console.log('Running container');
    await runContainer({
      imageId,
      port: PORT,
      env: [
        ...ENV,
        {
          name: 'AUTH_CALLBACK_URL',
          value: 'http://localhost:3000/auth/callback',
        },
      ],
    });
  });
}

// basically runs container.sync then grabs the image path
export async function buildContainer({ runner }: { runner: Container }) {
  const container = await runner.sync();
  console.log('Container built');
  const exportPath = `${os.tmpdir()}/${uuid()}.tar`;
  const exported = await container.export(exportPath);
  if (!exported) throw new Error('Failed to export image');
  return exportPath;
}

// loads the image from the path from previous function, then grabs the id
export async function loadContainer({ path }: { path: string }) {
  const dockerLoadResult = await $`docker load -i ${path}`;
  const [, imageId] = dockerLoadResult.stdout.split('sha256:');
  if (!imageId) throw new Error('Failed to determine imageId');
  return imageId.trim();
}

type Env = { name: string; value: string };

// runs the container from image id with provided environment variables & port if applicable
export async function runContainer({
  imageId,
  port,
  env = [],
}: {
  imageId: string;
  port: number;
  env?: Env[];
}) {
  let args: string[] = [];
  args = env.reduce((args, { name, value }) => {
    return [...args, '-e', `${name}=${value}`];
  }, args);
  try {
    await $({
      stdio: 'inherit',
    })`docker run --rm ${args} -p ${port}:${port} ${imageId}`;
  } catch (error) {
    console.error('Failed while running container', error);
  }
}
dawn comet
#

Hey @upbeat raven , looks pretty cool! We'll have support for this very soon directly in dagger (https://github.com/dagger/dagger/pull/5557) where you'd actually be able to just

proxy= await container.proxy("127.0.0.1").start()
GitHub

This PR combines a few efforts that have been piling up throughout our chaotic Zenith adventures; sorry for the huge PR:

Switch services to run via the gateway interface instead of via Solve() (pr...

upbeat raven
#

excellent! thank you!

hallow loom
#

I think the post-bikeshedding API looks a little different ๐Ÿ˜› But the functionality remains the same. And yes it will be awesome ๐Ÿ™‚

lament tundra
#

Apologies in advance if Iโ€™m hijacking this thread, but Iโ€™m doing something a bit similar to build dev containers for developers, Because of nix and bazel caching the containers end up being huge and take forever to export and import back into Docker.

Seeing that PR makes me wonder whether a better approach would be to run a ssh server at the end of the container build. Then people could dev in the container without needing to export it, and we could use cache volumes.

hallow loom
# lament tundra Apologies in advance if Iโ€™m hijacking this thread, but Iโ€™m doing something a bit...

Sure why not! There are two upcoming features that will help support this use case:

  1. Host-to-container networking. This will allow service containers to be reachable from the host. So you could run an ssh server as part of your DAG, then devs can ssh into it from the host machine.

  2. Interactive shell. This will allow the Dagger CLI to connect to execute an interactive shell inside a container, and attach it to the user's terminal - all via Dagger. Probably via a command like dagger shell or equivalent.

lament tundra
#

Is the interactive shell work issue #3024?

hallow loom
#

That's a different feature (interactive debugging of your DAG), although built on the same plumbing