Skip to content

Create an instance from your own image

View as Markdown

Run a TIR Instance from your own container image, either from your project’s Container Registry or from a public registry such as Docker Hub. An image that already holds your packages starts the same way every time, while packages you install in a running instance are lost each time its container restarts.

The task has three parts: build the image, push it to a registry, and launch an instance from it under Custom Images.

  • Docker on a machine of your own, to build the image. An instance is itself a container with no Docker daemon; to build on TIR instead, use Save Image or BuildKit, as Build the image describes.
  • For a private image, a namespace in your project’s Container Registry, which is in the side menu under Storage. The Private tab lists every namespace in the project’s Container Registry in that region. See TIR Container Registry.
  • An SSH key in your TIR SSH Keys. The form asks for a key and a security group that opens port 22 for every custom image, even with JupyterLab Support ticked.
  • Everything a new instance needs, such as credit on a prepaid account. See Create an instance.

Use a private image, from your project’s Container Registry, to launch from an environment you already set up and saved, or to give the instance a framework or configuration beyond what the pre-built images offer. A private image is also the way to give every project member the same environment.

Use a public image, such as one from Docker Hub, to launch from an image someone else built: a well-known image, or one a vendor or community maintains. You work in a public image over SSH.

TIR starts a custom or public image with its own setup in place of the image’s start command, so build the image with that in mind.

  • Base the image on Ubuntu. TIR’s setup installs its tools with apt-get. If the image runs as a user other than root, give that user passwordless sudo.
  • Build it for linux/amd64. TIR checks a public image for that platform when you enter it.
  • Move anything the image’s entrypoint or command used to start into a start script, because TIR’s setup runs in place of the entrypoint.
  • Start background programs from a start script. An instance runs without systemd, so systemctl does not work.
  • Keep shell settings, such as an export PATH=... line, in the image or in a start script. At every start, .bashrc and .profile in /home/jovyan are replaced with the ones in /root, so changes you make to them in a running instance are lost.

What happens at start-up depends on what the image is built on:

  • On a TIR pre-built image, TIR’s setup hands over to that image’s own start-up, so its app and SSH start as they do on a pre-built image.
  • On any other image, TIR’s setup runs as root and sets HOME to /home/jovyan. It installs sudo, curl, git, wget, vim, unzip, zip, a few other basic tools, an SSH server, and an SFTP server. It turns off password login, runs your start scripts as root, and starts SSH, and you log in as root with your key. After installing its tools, the setup clears the package lists, so run apt-get update before you apt-get install anything.

On those other images, TIR runs your start scripts one after another, waiting for each one to finish, and starts SSH only after the last. Start a program that keeps running in the background, for example with nohup <command> &, so that the script returns and SSH can start.

An instance from a custom or public image shows Running once SSH answers on port 22.

JupyterLab runs on a custom image only when it was made with TIR’s image builder, or is based on a TIR pre-built image that has JupyterLab. Tick JupyterLab Support when you launch such an image from Private. You work over SSH in every other custom image and in every public image.

Pick the way that suits you:

Way to build Choose it when
A Dockerfile on one of TIR’s own base images You want JupyterLab and SSH to work as on a pre-built image, and a build you can repeat. Start here.
A Dockerfile on a base image of your own You already have a base image, and you work in the instance over SSH
By hand, with docker commit You prefer to install packages interactively and save the result
Save Image on a running instance You have already set up an instance the way you want it
BuildKit, on an instance You have a Dockerfile and want to build it on TIR

The quickest way to a working image is to start from one of TIR’s own pre-built images. They already have TIR’s start-up, JupyterLab, and SSH, anyone can pull them, and they stay compatible once you add your own packages.

  • aimle2e/ubuntu-cuda-jupyter:22.04-12.2.2: Ubuntu with CUDA and JupyterLab only.
  • aimle2e/nvidia-pytorch:23.06-2.1.0: PyTorch 2.1.0.
  • aimle2e/nvidia-tensorflow:23.06-2.12.0: TensorFlow 2.12.0.
  • aimle2e/nvidia-pytorch-transformers:23.06-2.1.0-4.31.0: PyTorch 2.1.0 with Hugging Face Transformers 4.31.0.

Name one of these in your Dockerfile’s FROM line, add your packages, and build it, tagging it with its full registry path so the next step can push it straight away:

FROM aimle2e/nvidia-pytorch:23.06-2.1.0
RUN pip install --no-cache-dir <your-package>
docker build --platform linux/amd64 -t registry.e2enetworks.net/<namespace>/<image>:<tag> .

Replace <namespace> with your Container Registry namespace, <image> with the name you want for the image, and <tag> with its version.

You can also start from your own base image. In your Dockerfile, start from your base image with FROM --platform=linux/amd64 followed by the base image’s name, add your packages, and build it for linux/amd64:

docker build --platform linux/amd64 -t <image-name>:<tag> .

Replace <image-name> with the name you want for the image, and <tag> with its version, such as v1. On an Apple silicon Mac, keep --platform linux/amd64. TIR checks the platform only for a public image, when you enter it, so build every image for linux/amd64.

A Dockerfile is easier to repeat, but you can also build the image by hand: run a container from a base image, install your packages in it, and save the result as a new image.

docker run --platform linux/amd64 -d <base-image>
docker exec -it <container-id> /bin/bash

Install your packages in the container, then leave it, and save your changes as a new image, tagged with its full registry path:

docker commit <container-id> registry.e2enetworks.net/<namespace>/<image>:<tag>

Replace <namespace> with your Container Registry namespace, <image> with the name you want for the image, and <tag> with its version. Then log in and push it; see Push the image to Container Registry.

To start from an instance you have already set up instead, install your packages on it and save it with Save Image. TIR saves the container as an image in a namespace of your Container Registry, ready to launch. See Save an instance as an image.

To build from a Dockerfile on TIR itself, run BuildKit on an instance; it builds the image and pushes it to your Container Registry in one step. See Build container images with BuildKit.

In the side menu, under Storage, open Container Registry, and in your namespace’s row select the terminal button under Commands. Docker Commands gives the three commands to run:

  • the Docker Login Command, which logs in with the namespace’s own username and password, a different login from your TIR sign-in
  • the docker tag command, which names the image <registry>/<namespace>/<image>:<tag>
  • the docker push command

The registry is registry.e2enetworks.net in Delhi and in-south1-registry.e2enetworks.net in Chennai. Run the commands on the machine where you built the image. If the push is refused for authentication, log in again with those commands. Once the push finishes, the image is ready to launch. For the registry’s side of this step, see Push an image.

For a public image, push it to its public registry the way you usually do, and make sure the repository is public, so anyone can pull the image.

  1. In TIR, under Compute, select Containers (Instances), then Create Instance.
  2. In Choose Image, open Custom Images, then Private.
  3. If you built the image with TIR’s image builder or on a TIR pre-built image, tick JupyterLab Support so that the instance gets JupyterLab. Leave it clear for any other image.
  4. Under Registry Namespace, pick your namespace in the project’s Container Registry for this region. If there is none yet, follow the field’s link to create one.
  5. Under Available Images, find your image. Use Search Image to find it by name, and the refresh button if you pushed it a moment ago.
  6. Choose the tag in the image’s list, or select the image to use its first tag. You can still change the tag in Version at the top of the form.

If the namespace is still empty, its commands link gives the Docker commands to push an image. Images you saved from another instance are listed here too, the same way.

  1. In TIR, under Compute, select Containers (Instances), then Create Instance.
  2. In Choose Image, open the Custom Images tab, and stay on Public.
  3. Type the image’s name with its tag after a colon, such as ubuntu:22.04, docker.io/library/ubuntu:22.04, or pytorch/pytorch:latest. Include the tag, even for a well-known name such as pytorch/pytorch. The name can be up to 128 characters.
  4. Wait for TIR to check the image as you type. It checks that the image exists, that it is public, and that it supports linux/amd64. When the image passes, the field says Image is valid. Otherwise it says what is wrong, such as a missing tag or a private repository. If TIR fails to reach the registry for the check, you can still continue, and the image goes unchecked.
  5. Select Next. The Create Instance form opens for the image.

TIR checks a public image again each time the instance starts, and refuses the start if the image fails that check.

The rest of the form works as it does for any instance: name, computing resource, billing, storage, network, and start scripts. See Create an instance for each choice. Two parts matter most for your own image:

  • Pick at least one SSH key under SSH Keys, and a security group that opens port 22 under Security Group; the form asks for both for every custom image. If you pick a key and leave the group empty, the form selects the project’s default group, which opens port 22.
  • Under Startup Script, pick the start scripts that do what the image’s entrypoint used to do.

Select Launch Instance. The instance shows Waiting while the host downloads the image and TIR’s setup runs. Each time the instance starts, TIR asks the registry for the image and downloads the parts of it the host is missing. A large image therefore keeps the instance on Waiting for longer. If the image or its tag is removed from the registry, the instance stays on Waiting. See Troubleshooting TIR Instances.

Once the instance is Running, connect over SSH as root with your key, using the command the instance’s page shows. See Connect to an instance over SSH. If you ticked JupyterLab Support, you can open JupyterLab from the instance’s App URL instead. Run the tools you added to the image to confirm they are there.

Use Docker images without Docker on the instance

Section titled “Use Docker images without Docker on the instance”

An instance is an unprivileged container. You are root inside it, but it cannot run the Docker daemon or load kernel modules, so Docker commands that need the daemon do not work there. Use these instead:

  • To run your own Docker image, build it and push it from another machine, or with BuildKit on an instance, then launch it from Custom Images.
  • To keep packages you add inside an instance, save it as an image; see Save an instance as an image.
  • To run Docker itself, use a MyAccount GPU node, a full virtual machine. Its GPU images built on Ubuntu 22.04 come with Docker and the NVIDIA Container Toolkit; on Ubuntu 24.04 you install both yourself.

Tag your image with a version, such as v1.2, instead of relying on latest, so you can relaunch the same environment later. Rebuild and push the image again from time to time, to pick up security updates for the packages in it.

To add more packages and keep the same image, install them from a start script; see Run start scripts on an instance.