In this tutorial, we deploy a containerized web application to Quake AI. By the end, you will have a running Docker container serving a web page on a cloud instance, accessible from the internet through the instance's PublicEphemeral public IP.
What you will learn:
How to install Docker on a Quake AI instance
How to write a simple Dockerfile for a static website
How to build and run a Docker container on a remote server
How to open HTTP ports in a security group for web traffic
How to verify your application is accessible from the internet
Time estimate: 30 minutes
Click to zoom
What you'll build: a Docker container running on an Ubuntu instance, exposed to the internet through a security group and its PublicEphemeral public IP
Monthly total for the required template above. Use the configurator below to add optional pieces and see the total update.
What each resource is for
s1a.micro
s1a.micro · 1 shared vCPU, 1 GiB RAM, 0.5 Gbps
$8.25/mo
Compute shown per role at custom-package rates ($29/dedicated vCPU, $7.25/shared vCPU, $1/GiB RAM). The headline above is the billed total: the cheaper of a named plan and the custom package, plus add-ons.
Private networks, subnets, Neutron routers, and security groups are included with the plan.
VPC objects are usually free to create elsewhere, but NAT gateways bill hourly plus per-GB processed. Quake AI uses router SNAT with no separate NAT line item.
$0.00
Control-plane API requests
OpenStack API calls for provisioning and management are included.
Some managed services on other clouds meter API calls or charge for premium control-plane features.
$0.00
Pricing data last validated: . For current rates, check quake.ai/pricing.
SSH access to your instance (or create a new one following that tutorial)
Basic familiarity with the command line
This tutorial assumes Ubuntu 24.04 on the instance reachable over its PublicEphemeral public IP, which the network assigns at boot with no floating IP add-on. We refer to that address as YOUR_INSTANCE_IP throughout.
Step 1: Allow SSH and HTTP, then launch the instance#
We need inbound TCP 22 for administration and 80 for HTTP. Security groups enforce those rules at the network edge before traffic reaches the instance.
If you are creating a new instance:
Go to Network > Security Groups > Create Security Group. Name it tutorial-web and add a short description.
Add an ingress rule for SSH (port 22) from a CIDR you trust. For learning, 0.0.0.0/0 is common; tighten this in production.
Add an ingress rule for HTTP (port 80) from 0.0.0.0/0 so browsers and health checks can reach nginx.
Launch an instance at Compute > Instances > Create Instance:
Image:Ubuntu-24.04
Flavor:s1a.micro (1 vCPU, 1 GiB RAM), the entry-tier footprint
Network: attach PublicEphemeral, which assigns a public IP at boot
Security groups: include default and tutorial-web (or equivalent) so both platform defaults and your SSH/HTTP rules apply
Key pair: the same key you use for SSH
Copy the public IP the instance shows once it is Active. Note it as YOUR_INSTANCE_IP.
If you reuse the instance from Deploy your first server:
Edit your security group (or create tutorial-web as above) and add an ingress rule for HTTP on port 80.
Attach the updated group to the instance if it is not already applied.
Use the instance's existing PublicEphemeral public IP as YOUR_INSTANCE_IP.
Wait until the instance shows Active before continuing.
Docker packages your app and its runtime together so nginx runs the same way on every host. We use the official Docker apt repository so updates track Docker's supported packages on Ubuntu 24.04.
If you are already logged in from Step 2, run the install and group commands below. The first block repeats the SSH line for anyone joining mid-tutorial.
Add your user to the Docker group so you can run commands without sudo:
sudo usermod -aG docker ubuntu
newgrp docker
Group membership changes take effect on your next login. The newgrp docker line above activates the group in your current shell. If you skip it or open a new shell, log out and SSH back in before you run docker commands.
Confirm the install with a command that needs the daemon socket:
docker run --rm hello-world
A daemon-less check such as docker --version passes even when the group is not active yet, so it hides this gotcha.
Confirm Docker can reach its daemon:
bash
docker run --rm hello-world
Docker pulls a small test image and prints a message that starts with Hello from Docker!, confirming the daemon is reachable from your user account.
Step 3a: Configure swap (Developer Plan and other low-RAM tiers)#
If you are on the Developer Plan or any flavor with 2 GiB or less of RAM, add 1 GiB of swap before running containers. This prevents out-of-memory kills when a container spikes:
We keep a small static site so we focus on containers, not application frameworks. nginx serves index.html on port 80 inside the container.
bash
mkdir -p ~/container-demo && cd ~/container-demo
Create index.html:
HTML
<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <title>Quake AI container demo</title> </head> <body> <h1>Hello from Docker on Quake AI</h1> <p>If you see this page, your container and security group are configured correctly.</p> </body></html>
Create Dockerfile:
Dockerfile
FROM nginx:alpineCOPY index.html /usr/share/nginx/html/index.html
nginx:alpine is a small image with a production-grade web server, which keeps pull and build times short.
curl checks the stack from the server itself before we involve the public network path.
bash
curl -sS http://127.0.0.1/ | head -n 5
You should see the HTML title or heading from index.html. If the command hangs or fails, run docker ps and docker logs YOUR_CONTAINER_NAME to confirm the container is running.
Open http://YOUR_INSTANCE_IP in a desktop or mobile browser. You should see the demo heading and paragraph. Browsers follow redirects and cache behavior differently than curl, so this step confirms real user traffic works.
Multi-service stacks with Docker Compose (optional)#
Once your single-container app works, you can compose multiple services. Create ~/compose-demo/compose.yaml with explicit memory limits:
In the console: delete the instance at Compute > Instances to stop compute charges. The PublicEphemeral public IP is released with the instance, so there is no floating IP to release.
Optional: remove the tutorial-web security group if you created it for this walkthrough.
Usage Guidelines
The sample code, software libraries, command line tools, proofs of concept, templates, and other related technology on this page (including any of the foregoing that is provided by Quake AI personnel) is provided to you as Quake AI Content under the Quake AI Customer Agreement, or the relevant written agreement between you and Quake AI (whichever applies). Do not use this Quake AI Content in your production accounts, or on production or other critical data. You are responsible for testing, securing, and optimizing the Quake AI Content (such as sample code) as appropriate for production grade use based on your specific quality control practices and standards. Deploying Quake AI Content may incur Quake AI charges for creating or using Quake AI chargeable resources, such as running Compute instances or storing data in Object Storage. Your use is also subject to the Acceptable Use Policy.