iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more
To run an application on Azure Container Instances (ACI), build a Docker image from your Dockerfile, test that image on your own machine, push it to Docker Hub under a name ACI can pull, and then create a container group that exposes the exact port your application listens on. Most failed deployments trace back to one of three points: the image does not start, the image reference is wrong, or the port in the Azure command does not match the port inside the container.
The workflow in order
The path from source code to a public endpoint has five stages. Each one produces something the next stage depends on, so it is worth checking each before moving on.
- Dockerfile and build context. A Dockerfile describes how to build an image from your application files.
- Image.
docker buildturns the Dockerfile and its build context into an image, which is a standalone package containing what the application needs to run. - Local run. A container is a running instance of an image. Running the image on your machine confirms that the application starts and responds before Azure is involved.
- Registry push. The image is tagged with your Docker Hub namespace and pushed so that Azure can pull it.
- ACI deployment and checks. You create a container group, confirm its provisioning state and fully qualified domain name (FQDN), then read its logs.
Step 1: Write the Dockerfile and test the image locally
Choose a runtime you can keep supported
Microsoft’s ACI image preparation tutorial, last updated 17 November 2025, uses a Node.js sample that starts from node:8.9.3-alpine. That version is long out of support, so treat the tutorial as a demonstration of the workflow, not as a template for the base image. Pick a base image tag for a currently supported runtime release and use that for your own application. The example below uses a placeholder you must replace with a supported tag:
FROM node:<supported-lts-version>-alpine
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
EXPOSE 8080
CMD node server.js
Two details matter here. First, copying package*.json before the rest of the source lets Docker reuse the dependency layer when only application code changes. Second, the CMD must start the server in the foreground. If the process exits, the container exits, and ACI will show the instance repeatedly stopping.
#1 Best Overall
Build the image and run it locally
Build from the directory that contains the Dockerfile:
docker build -t aci-tutorial-app .
Run it with the local port mapped to the port your application listens on inside the container:
docker run -d -p 8080:8080 aci-tutorial-app
Then open http://localhost:8080. The tutorial maps 8080:80 because its sample app listens on port 80 inside the container. Use whatever port your own application actually binds to.
Recommended Free Tools
Rank #2
The tutorial’s sample output reported an image size of 68.1 MB. That figure comes from one run of one small sample, so treat it as an illustration of the output format rather than a benchmark for your image.
Step 2: Tag and push the image to Docker Hub
Log in, tag, and push
Docker Hub identifies an image by a namespace (normally your Docker Hub username), a repository name, and a tag. Run these commands in order:
docker login -u <username>
docker tag aci-tutorial-app <username>/aci-tutorial-app:v1
docker push <username>/aci-tutorial-app:v1
Docker’s CLI cheat sheet documents the docker login -u and docker push <username>/<image_name> forms. Adding an explicit version tag such as v1 is a practical habit: it makes it clear which build ACI is running, and it avoids depending on latest when you redeploy.
Rank #3
Public and private repositories
Whether your repository is public or private determines how ACI must authenticate when it pulls the image. A public repository can be pulled without credentials. A private repository requires registry credentials in the deployment command (covered in Step 3). Docker Hub’s current plan limits and its rules for public and private repositories change over time, so check them on Docker’s own pricing and repository pages before you rely on them for a production workload.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Step 3: Deploy to Azure Container Instances
Understand the quickstart values before reusing them
Microsoft’s Azure CLI quickstart for ACI creates a resource group and then a container instance from a public Microsoft sample image. It uses a DNS name label, port 80, Linux as the OS type, 1 CPU, and 1.5 GB of memory. Those values are the quickstart’s example configuration, not sizing advice. The table shows what to replace when you deploy your own image:
| Setting | Quickstart example | What to use for your application |
|---|---|---|
| Image | Public Microsoft sample image, mcr.microsoft.com/azuredocs/aci-helloworld |
Your Docker Hub image reference, for example <username>/aci-tutorial-app:v1 |
| DNS name label | A label chosen for the quickstart | A label that is unique for the region you deploy to |
| Port | 80 | The port your process actually listens on (8080 in the Step 1 example) |
| OS type | Linux | Linux, matching a Linux image |
| CPU | 1 | Set according to what your workload needs; the quickstart value is not a sizing recommendation |
| Memory | 1.5 GB | Set according to what your workload needs; the quickstart value is not a sizing recommendation |
Create the container group from the Docker Hub image
Create a resource group in a region you choose, then create the container instance:
Rank #4
az group create --name aci-demo-rg --location eastus
az container create --resource-group aci-demo-rg --name aci-tutorial-app --image <username>/aci-tutorial-app:v1 --os-type Linux --cpu 1 --memory 1.5 --ports 8080 --dns-name-label <your-unique-label>
ACI does not perform Docker-style port mapping. The value passed to --ports is the port that the container group exposes, and it must match the port your application listens on. Setting --ports 80 for an app that listens on 8080 produces a deployment that looks healthy but does not answer requests on the expected port.
For a private Docker Hub repository, the az container create command accepts registry credential options. Confirm the exact flag names for your Azure CLI version with az container create --help, and supply a Docker Hub access token rather than a password where your account allows it. Do not assume ACI will reuse your local docker login session.
Step 4: Verify the deployment
Read the provisioning state and FQDN first:
az container show --resource-group aci-demo-rg --name aci-tutorial-app --query "{state:provisioningState, fqdn:ipAddress.fqdn}" --output table
When the state reads Succeeded, open the FQDN with the port you configured, for example http://<fqdn>:8080. Next, read the application output:
Best Value
az container logs --resource-group aci-demo-rg --name aci-tutorial-app
Logs show what the process printed, including startup errors. Microsoft’s guidance on DNS notes that a newly configured DNS label can take a short time to propagate, so if the FQDN does not resolve immediately, wait briefly and try again before changing anything else.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Troubleshooting common failures
- Provisioning state is not
Succeeded. Runaz container showagain and then readaz container logs. Recheck the image reference, including the namespace and tag. - The container starts and then stops, repeatedly. The
CMDis probably not a long-running foreground process. Run the same command withdocker runlocally and confirm it stays up. - The FQDN resolves but the page times out. The port is the most likely cause. Compare the application’s listening port with the value given to
--ports, and remember that ACI does not map ports the waydocker run -pdoes. - Startup is slow. Image size and location both affect how long ACI takes to pull the image. Keep runtime images lean, consider a multi-stage build so build tools stay out of the final image, and, if you need faster pulls, Microsoft’s ACI troubleshooting guidance notes that storing the image in Azure Container Registry in the same region as the container group shortens the download path. That guidance concerns download time; it does not mean Docker Hub cannot work.
- A private image fails to pull. The registry credentials were missing or wrong. Redeploy with the credential options described in Step 3.
What to confirm for your own account
The steps above describe the workflow, but several details depend on your account and the date you deploy:
- Docker Hub plan limits, pull rates, and repository visibility rules, which Docker publishes and changes over time.
- Azure resource availability, regional DNS behavior, and permissions in the region you choose.
- ACI pricing for the CPU and memory you configure. The quickstart values do not indicate cost.
- Whether ACI fits your workload. Microsoft describes ACI as a solution for scenarios that can operate in isolated containers without orchestration. If you need orchestration, scaling across many containers, or networking features beyond a single container group, compare alternatives against current Azure documentation before committing.
Docker describes Docker Hub as “a service provided by Docker for finding and sharing container images with your team,” which is the role the image plays in this workflow: a place where ACI can pull a versioned image by name.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

