Containerized jumpbox with web-based console SSH in Azure Container Instances (ACI)

Salut! Have not written for a while since I joined new company back in this February! Here, in Azure we have so much awesome staff, so I could not really fine free time to keep running my blog with new ideas! With over dozen different options for microservice architecture, I fall in love with things like AKS, ACR, ACI etc.

If you are like me, enjoying to learn new staff and interested in containers around clouds, see what you can do with Azure Container Instances (ACI) and Azure Container Registry (aka ACR, or registry of you choice, like docker hub etc). There are multiple code samples of ACI (e.g. dockerized Wordpress, docker volume manager etc).

What is ACI?

Well, it is "serverless" container engine (of course it is serverfull, but as consumer of this service I don't have to worry about underlying computer facilities something like cluster or docker-machine). I can just use either Azure portal, CLI or Powershell to execute my container with image of my choice from any docker compatible registry. Sounds awesome, right? the pricing model is based on pay-as-you-execute (similar to runtime in Azure Functions with consumption model). The pricing page is here to help.

What is ACR?

If your journey with containers started from Docker Inc., you should be aware of it's hub. Great registry! However, let's imagine you need registry closer to your container's drivers or you need same code base available across the World for different developers. Also you may need your corporate identity integration as well (e.g. only authorized through AD users should be able to use your registries and objects within them). Finally, why do you need several places / portals for pretty the same set of tasks? Azure Container Registry allows you to store images for all types of container deployments including DC/OS, Docker Swarm, Kubernetes, and Azure services such as App Service, Batch, Service Fabric, and others. Your DevOps team can manage the configuration of apps isolated from the configuration of the hosting environment. And, last but not least, we are looking at the same docker CLI experience, so you do not have to relearn in order to use it. Just create registry, push your first image and enjoy.

What is jumpbox?

Jumpbox here is azure's compute resource with ssh server used for getting access to rest of other resources in the cloud. One of the option to do this is to run virtual machine with few ports (and may be inbound rules in NSG) opened for jumping in and then iterating with other VMs or services through internal (private) network. In this case we are running ssh daemon with shellinabox for accessing our resources through ssh through web browser. See below picture what exactly I mean.

Shellinabox view in chrome web browser with htop utility

Shell In A Box implements a web server that can export arbitrary command line tools to a web based terminal emulator. This emulator is accessible to any JavaScript and CSS enabled web browser and does not require any additional browser plugins.


You need:

  • Azure command-line interface on your computer (obviously, you also need subscription, there is free tier available as well);
  • Docker command-line interface;

Dockerfile for our jumpbox

The whole idea is based on Dockerize an SSH service with small modification. Let's create our image.

FROM ubuntu:16.04



RUN apt-get update && apt-get install -y openssh-server shellinabox
RUN mkdir /var/run/sshd
RUN echo 'root:$SECRET' | chpasswd
RUN sed -i 's/PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
RUN sed -i 's#--no-beep#--no-beep --disable-ssl --service=/:SSH#g' /etc/default/shellinabox

# SSH login fix. Otherwise user is kicked off after login
RUN sed 's@session\s*required\s* optional' -i /etc/pam.d/sshd

ENV NOTVISIBLE "in users profile"
RUN echo "export VISIBLE=now" >> /etc/profile


#CMD ["/usr/sbin/sshd", "-D"]

CMD /usr/sbin/sshd -D

There are two small changes I made in this image:

  • Added shellinabox package to installer;
  • Added sed for modification in /etc/default/shellinabox in order to disable ssl and inherit ssh settings (e.g. to allow root login etc).

For the sake of simplicity we don't create new user for ssh and we use default port (22).

Registry for images in Azure

Let's now push this to our personal container registry (as I said earlier there is ACR specifically for this).

Now, since we have Azure CLI in our computer, let's quickly do az login and by following instructions get access to our portal (there will be link with random code to paste in it). Once done, you will see the output of all available subscriptions under this user. Now, let's create registry.

az acr create -n acr -g acr --sku basic|standard|premium

I went for basic sku for my registry, but you want to use better tiers (you can always switch this through portal or CLI).

Once, registry is ready, we can . setup service principal in order to authorize or we can always type username and password to access it. Let's use second option, since we want simplicity. As I said earlier your experience is absolutely the same as docker cli. To push you use this:

# Some variables


az group create -n $RG_NAME --location $REGION && \
docker build -t $ACI_NAME . && \
docker tag $ACI_NAME $IMAGE_NAME && \
docker push $IMAGE_NAME && \

There is az group command for new Azure Resource Group (RG). In Azure we keep all resources in RG, which is great way to structure your services and manipulate them (delete, move etc..). In environment variables we keep all names (you need to change them to yours).

If there were no errors (like in my case), we can continue to the main action, - creating container.

Launching jumpbox container

PORTS="22 4200"

az container create \
  -n $ACI_NAME \
  -g $RG_NAME \
  --image $IMAGE_NAME \
  --ip-address public \
  --dns-name-label $DNS_LABEL \
  --ports $PORTS

I've added one more variable with array of ports to pass them to my container instance. In this particular cli above we take image from registry and create new containers and exposing few ports in order to interact with them. Port 4200 is used by shellinabox app by default (you can change this if you want, then you need to do some find_and_replace operations with default configuration of this app).

If everything is ok, you should be able to see json format 'ish output with IP. But we don't need IP since we ordered DNS label. So your container can be accessed through ssh by default port 22 or through regular http browser with port 4200 (http://fqdn:4200). Default container's fqdn should be like this (where dns_label and region are your data from environment variables).


Once done, you can clean up by deleting your container through cli or portal. I put together Dockerfile and shell script for building, pushing and creating on github.

Shell in a box in action

In short, this is about:

Start discussion:
Related articles:
Docker opens wide range of options for applications delivery. It is not just deployment tool, but great for testing and development. Even for production ... ... more
over 4 years#rails #docker
Build and release docker compose application using Azure DevOps in an automated manner using multistage yaml pipeline. ... more
This article contains several recommendations for passing kubernetes exams (both CKAD and CKA). ... more
As an engineer I want to pull container images that are part of my pods' deployments to Azure Kubernetes Service (further - AKS) from private container registry Azure Container Registry (further - ACR). But when I create pod with image from ACR it fails with ErrImagePull error. How to fix this? ... more