Deploy a Flask App with Docker and Render
Containerize a Flask app with Docker and deploy it live on Render.
Introduction
30 Second Summary
You have built something cool on your laptop. But right now, nobody else can use it unless they sit at your desk.
In this project, you will take your DSA learning assistant and deploy it to a live public URL that anyone can access. You will use Docker to package your app into a portable container, then ship it to the cloud with Render.
What You'll Build
You will open a browser on your phone, visit your app's public URL, and ask your AI-powered DSA assistant a question from anywhere in the world.
By the end of this project, you'll have:
- An app that runs identically whether it is on your laptop, a colleague's machine, or a cloud server, because Docker containers guarantee the environment is the same everywhere.
- A working CI/CD pipeline where pushing code to GitHub automatically redeploys your live site within minutes.
- Your Gemini API key stored securely as an environment variable, never exposed in your code or Docker image.
- Secret Mission: Add a health check endpoint and wire it into Render's monitoring so the platform knows your app is alive and working.
Are there any prerequisites?
This project assumes you already have a working Flask app with a Google Gemini API integration, basic Python knowledge, and familiarity with Git basics (push, pull, commit). You should also have Docker Desktop installed on your machine.
Before We Start
Before we dive in, let's lock in what you're about to build and why it matters. Taking a moment to articulate your goals turns this from a follow-along exercise into a real learning experience.
Push Your Project to GitHub and Verify Docker
Your DSA learning assistant currently lives on your machine. To deploy it to the cloud with Render, the code needs to live in a GitHub repository that Render can pull from.
In this step, you'll push your project to GitHub and confirm Docker is ready for the containerization work that comes next.
In this step, get ready to:
- Create a .gitignore file and initialize a git repository.
- Push your project to a new GitHub repository.
- Verify Docker Desktop is accessible from the command line.
Create a .gitignore and initialize your repository
Before tracking your project with Git, you need a .gitignore file to prevent sensitive files and unnecessary folders from being committed.
- In Antigravity IDE, click File in the top menu bar.
- Click Open Folder.
- Select your DSA learning assistant project folder, then click Open.
Your project files now appear in the Explorer sidebar on the left.
- In the Explorer sidebar, click the New File icon (it looks like a page with a plus sign).
- Type .gitignore as the file name and press Enter.
- Paste the following content into the new file:
venv/
__pycache__/
.env
*.pyc
What does this file do?
- venv/ excludes your virtual environment folder. It's large and can be recreated with pip install.
- __pycache__/ excludes Python's compiled bytecode cache. It's auto-generated.
- .env excludes your environment variables file. This keeps your Gemini API key out of GitHub.
- *.pyc excludes individual compiled Python files anywhere in the project.
- Save .gitignore by pressing Cmd+S (macOS) or Ctrl+S (Windows).
File not appearing in the sidebar?
Make sure you typed the name starting with a dot: .gitignore. Files starting with a dot are hidden by default on some systems, but Antigravity's Explorer shows them.
If you accidentally created it without the dot, right-click the file in the Explorer and select Rename to fix it.
help me create a .gitignore file in Antigravity IDE
✔️ Awesome, I've got everything!
Great. Make sure you've saved .gitignore before moving on.
ⓧ I'd like to double check the full code
Your .gitignore file should contain exactly this:
venv/
__pycache__/
.env
*.pyc
Now initialize a git repository and make your first commit.
- Open the integrated terminal by pressing Ctrl+` (backtick key, same shortcut on macOS and Windows).
- Initialize your repository and commit all files by running these commands:
git init
git add .
git commit -m "Initial commit"
What do these commands do?
- git init creates a new git repository in your project folder.
- git add . stages all files (except those listed in .gitignore) for your first commit.
- git commit -m "Initial commit" saves a snapshot of your project with a descriptive message.
- Confirm your commit worked by running:
git log --oneline
You should see one line with a short commit hash followed by Initial commit.
Seeing 'error: initial commit has no changes'?
This means git add . didn't find any files to stage. Make sure your terminal is inside your project folder (not a parent or child directory). Run ls to check that you can see your app.py and other project files listed.
help me fix my git init and first commit
Push your project to GitHub
Your code is committed locally. Now push it to GitHub so Render can access it when you deploy.
- In your browser, go to github.com and sign in.
- Click the + icon in the top-right corner.
- Click New repository.
- Enter a repository name (for example, dsa-learning-assistant).
- Leave the other settings at their defaults. You can choose public or private.
- Click Create repository.
GitHub shows a setup page with commands. You'll use the "push an existing repository" commands.
- Back in your Antigravity terminal, rename your branch to main and push by running these commands:
git branch -M main
git remote add origin [[YOUR_REPO_URL="https://github.com/your-username/your-repo-name.git"]]
git push -u origin main
What do these commands do?
- git branch -M main renames your current branch to main. This ensures your branch name matches what GitHub expects.
- git remote add origin connects your local repository to the GitHub repository you just created.
- git push -u origin main uploads your code to GitHub and sets main as the default branch to push to.
- Refresh your GitHub repository page in the browser.
You should see all your project files listed on the repository page, including app.py, requirements.txt, your templates folder, and .gitignore.
Push rejected or authentication failed?
If you see a permission error, GitHub may need you to authenticate. GitHub no longer accepts passwords for git operations. You need either a Personal Access Token or SSH key.
The quickest fix: go to Settings > Developer settings > Personal access tokens > Tokens (classic) on GitHub. Generate a new token with repo scope and use it as your password when prompted.
help me push my code to GitHub from Antigravity IDE
Verify Docker is accessible
The last piece of setup is confirming Docker Desktop is running and accessible from your terminal. You'll use Docker in the next step to containerize your app.
- Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
- Type Docker Desktop and press Enter to open it.
- Wait until the Docker Desktop window shows the dashboard (you may see a whale icon in your system tray or menu bar indicating it's ready).
Before you run the next command, what do you expect to see if Docker is set up correctly?
- Switch back to your Antigravity terminal and verify Docker is accessible by running:
docker --version
You should see a version number printed, something like Docker version 27.x.x. The exact number doesn't matter as long as you get a response.
Seeing 'command not found'?
This usually means Docker Desktop hasn't finished starting up. Wait 30 seconds and try again.
If it still fails, open Docker Desktop and check that the bottom-left status indicator shows a green "Engine running" state. On Windows, make sure the WSL 2 backend is enabled in Docker Desktop's Settings > General.
help me get docker --version working in my terminal
Your project is on GitHub and Docker is ready. Next up, you'll write a Dockerfile and build your first container.
Containerize Your App with Docker
Your code is safely on GitHub and Docker Desktop is running. Now it is time to package your entire app into a container that runs identically on any machine.
Right now your app depends on your laptop's specific Python version, installed packages, and file paths. A Docker container bundles all of that into one portable unit. You will build that unit in this step and see your app running inside it.
In this step, get ready to:
- Add a production web server (Gunicorn) and create a Dockerfile.
- Create a .dockerignore to keep secrets and junk out of your image.
- Build and run your first Docker container.
Add Gunicorn and create your Dockerfile
Flask's built-in server is designed for local development only. Production apps need a proper web server that can handle multiple requests at once. Gunicorn is the standard production server for Python web apps.
- Open requirements.txt in your editor and add gunicorn on a new line at the end of the file:
gunicorn
Why Gunicorn instead of Flask's dev server?
Flask's built-in server is single-threaded and will crash under real traffic. Gunicorn spawns multiple worker processes to handle requests in parallel.
Render's own Flask deployment guide uses Gunicorn as the start command. Adding it now means your container is production-ready from the start.
Now you will create the file that tells Docker how to build your app's container image.
- Create a new file called Dockerfile (no file extension) in your project root and paste this code:
# Use a lightweight Python image as the base
FROM python:3.12-slim
# Set the working directory inside the container
WORKDIR /app
# Copy and install dependencies first (for Docker layer caching)
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy the rest of your app code
COPY . .
# Document which port the app listens on
EXPOSE 10000
# Start the app with Gunicorn
CMD ["gunicorn", "--bind", "0.0.0.0:10000", "app:app"]
What does this Dockerfile do?
- FROM python:3.12-slim starts from an official Python image with minimal extras, keeping the container small.
- COPY requirements.txt . followed by RUN pip install installs your dependencies before copying code. Docker caches this layer so rebuilds are fast when only code changes.
- EXPOSE 10000 documents that your app listens on port 10000 (Render's default port for web services).
- CMD ["gunicorn", "--bind", "0.0.0.0:10000", "app:app"] starts Gunicorn, binding to all interfaces on port 10000 and serving your Flask app.
Using a different filename for your Flask app?
The app:app part means "find the Flask instance named app inside a file called app.py." If your Flask file is named something else (like main.py), change it to main:app.
- Save both requirements.txt and Dockerfile.
- Confirm the Dockerfile exists by running:
ls Dockerfile
You should see Dockerfile printed in the output.
Don't see the file?
- Make sure you created the file in your project root (the same folder where app.py lives), not inside a subfolder.
- Confirm the filename is exactly Dockerfile with a capital D and no extension (not Dockerfile.txt).
Can't figure out what went wrong? Help me troubleshoot my Dockerfile setup.
✔️ Awesome, I've got everything!
Great. Double check you have saved both files before moving on.
ⓧ I'd like to double check the full code
Here is the complete Dockerfile:
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 10000
CMD ["gunicorn", "--bind", "0.0.0.0:10000", "app:app"]
Create a .dockerignore file
When Docker builds your image, it copies your entire project folder into the container. You need to exclude files that would bloat the image or leak secrets.
- Create a new file called .dockerignore in your project root and paste this:
venv/
__pycache__/
.env
.git/
*.pyc
.gitignore
Why exclude these files?
- venv/ is your local virtual environment. The container installs its own fresh dependencies from requirements.txt.
- .env contains your Gemini API key. You never want secrets baked into a Docker image that could be shared or pushed to a registry.
- .git/ is your version history. It adds bulk but serves no purpose inside the running container.
- Save .dockerignore.
- Confirm it exists by running:
ls .dockerignore
You should see .dockerignore printed in the output.
File not showing up?
Files starting with a dot are hidden by default. Run ls -a to list all files including hidden ones. You should see .dockerignore in the list.
Still stuck? Help me find my .dockerignore file.
✔️ Awesome, I've got everything!
Great. Double check you have saved the file before moving on.
ⓧ I'd like to double check the full code
Here is the complete .dockerignore:
venv/
__pycache__/
.env
.git/
*.pyc
.gitignore
Build and run your Docker container
Your Dockerfile and .dockerignore are ready. Time to build the image and see your app run inside a container.
- Build your Docker image by running this command:
docker build -t dsa-assistant .
What does this command do?
- docker build reads your Dockerfile and executes each instruction to create an image.
- -t dsa-assistant tags the image with the name dsa-assistant so you can refer to it easily later.
- . tells Docker to look for the Dockerfile in the current directory.
You will see Docker downloading the Python base image and installing your dependencies. This takes 1-2 minutes the first time. When it finishes, you will see a line containing Successfully tagged dsa-assistant or similar confirmation.
Build failing with an error?
- If you see a "no such file" error for requirements.txt, make sure you are running the command from your project root (the folder containing Dockerfile and requirements.txt).
- If you see a permission error, confirm Docker Desktop is running (check for the Docker whale icon in your system tray).
Need more help? Help me debug my Docker build error.
Before you run the container, think about this: what do you expect to see when you open the app in your browser? Will it work exactly like it does when you run it locally?
- Start a container from your new image by running:
docker run -p 10000:10000 dsa-assistant
What does this command do?
-p 10000:10000 maps port 10000 on your laptop to port 10000 inside the container. Without this flag, the container's port would be unreachable from your browser.
- Open your browser and navigate to http://localhost:10000.
You should see your DSA Learning Assistant homepage loaded in the browser. This page is being served from inside the Docker container, not from your local Python environment.
Page not loading?
- Check your terminal for error messages. If you see ModuleNotFoundError, a dependency is missing from requirements.txt. Add it, rebuild the image, and try again.
- If the terminal shows Gunicorn starting but the browser times out, confirm you used -p 10000:10000 in the run command.
- If you see address already in use, another process is using port 10000. Stop it or change the host port: docker run -p 5001:10000 dsa-assistant and open http://localhost:5001 instead.
Still stuck? Help me get my Docker container running on localhost.
Your app's homepage is live from inside a container. But what happens when you try to ask the AI a DSA question? The next step reveals a gap that every developer hits when containerizing apps with secrets.
Fix the Broken AI with Environment Variables
Your Docker container serves the homepage at http://localhost:10000. But the AI feature tells a different story.
Your Gemini API key lived in a local .env file, and .dockerignore correctly excluded it from the image. The container has no way to call the API.
This is actually the correct behavior. You never want secrets baked into a Docker image because anyone who pulls that image gets your key. Instead, you pass secrets at runtime using environment variables.
In this step, get ready to:
- Confirm your Flask app reads the API key from an environment variable.
- Re-run the container with the API key passed in at runtime.
- Commit and push your Docker support code to GitHub.
Confirm your code reads the API key from an environment variable
For the container to receive the API key at runtime, your Python code needs to read it from the system environment rather than from a file. The standard pattern uses os.environ.get().
- Open your main Flask file (app.py or whatever you named it) in the Antigravity editor.
- Find the line where your Gemini API key is configured.
- Check whether it uses the following pattern:
import os
# Read the API key from system environment variables
api_key = os.environ.get("GEMINI_API_KEY")
✔️ My code already uses os.environ.get
You're all set. If your code uses os.environ.get("GEMINI_API_KEY") (even alongside load_dotenv()), it will read the key from whatever environment variable is available at runtime. No code change needed.
ⓧ My code hardcodes the key or reads it differently
docker build -t dsa-assistant .
Why rebuild?
The Docker image is a snapshot of your code at the moment you built it. If you changed app.py, you need a fresh build so the image contains the updated code.
Why does load_dotenv still work?
If your code uses load_dotenv() followed by os.environ.get(), that's fine. When the .env file is missing, load_dotenv() silently does nothing. The os.environ.get() call then reads from actual system environment variables instead.
Stop and re-run the container with your API key
Now you'll pass your Gemini API key into the container at runtime using Docker's -e flag. This injects the key as an environment variable without ever writing it to disk.
- Return to the terminal where your container is running.
- Press Ctrl+C to stop it. If that doesn't work, open a new terminal and run:
docker stop $(docker ps -q)
What does this command do?
The docker ps -q part lists running container IDs. Wrapping it in docker stop stops all of them. This is a quick way to clean up when you don't know the container ID.
Before you re-run the container with the API key, do you think the AI feature will work this time? What's different from the last run?
- Re-run the container with your API key injected by running:
docker run -p 10000:10000 -e GEMINI_API_KEY=your-actual-key dsa-assistant
What's happening here?
- -p 10000:10000 maps port 10000 on your machine to port 10000 inside the container.
- -e GEMINI_API_KEY=your-actual-key injects your API key as an environment variable that os.environ.get("GEMINI_API_KEY") can read.
- Replace your-actual-key with the real Gemini API key from your .env file.
- Open http://localhost:10000 in your browser.
- Ask the AI a DSA question (for example, "What is a binary search tree?").
This time the AI responds with a real answer. The key you passed via -e is now available inside the container as an environment variable, and your code reads it successfully.
AI still not responding?
- Double check that you replaced your-actual-key with your real Gemini API key (no quotes around the value in the command).
- Make sure the environment variable name in your docker run command matches exactly what your code reads. If your code uses os.environ.get("GEMINI_API_KEY"), the flag must be -e GEMINI_API_KEY=....
- If you updated your code in the previous substep, confirm you rebuilt the image before running.
Still stuck? Help me debug why my Docker container can't read the GEMINI_API_KEY environment variable.
Commit and push to GitHub
Your containerized app works locally with the API key passed at runtime. Time to push all of your Docker support files to GitHub so Render can access them in the next step.
- Stop the running container with Ctrl+C in your terminal.
- Stage, commit, and push your changes by running:
git add .
git commit -m "Add Docker support"
git push
What gets pushed?
This commits your Dockerfile, .dockerignore, .gitignore, and any code changes you made. Your .env file stays out of the repo because .gitignore excludes it.
- Open your repository page on GitHub in your browser.
- Confirm you can see your Dockerfile and .dockerignore in the file list.
Push rejected or failed?
- If you see a "rejected" error, run git pull --rebase origin main first, then try git push again.
- If you see "fatal: not a git repository", make sure your terminal is inside your project folder.
Need help? Help me fix a git push error when pushing my Docker project to GitHub.
Your app runs securely inside a container with the API key passed at runtime. Next up, you'll deploy this same container to Render and get a public URL anyone can access.
Deploy to Render
Your container runs perfectly on your laptop. The next step is getting it onto the internet where anyone can access it.
Render is a cloud platform that reads your Dockerfile, builds the image, and serves it at a public URL. Because you are using the same Dockerfile, the cloud version behaves identically to what you tested locally.
In this step, get ready to:
- Sign up for Render and connect your GitHub repository.
- Configure Docker deployment settings and add your API key.
- Deploy your app and verify it is live at a public URL.
Sign up for Render and connect your repository
Render needs access to your GitHub repository so it can pull your code and build the Docker image in the cloud.
- Open your browser and go to render.com.
- Click Get Started and sign up using your GitHub account.
- GitHub will ask you to authorize Render to access your repositories. Click Authorize to confirm.
- Once redirected back to the Render Dashboard, click New in the top-right corner.
- Select Web Service from the dropdown.
- Under the source options, select Git Provider and connect your GitHub account if prompted.
- Find your DSA assistant repository in the list and click Connect.
Why does Render need GitHub access?
Render pulls your code directly from GitHub every time it deploys. This connection also enables automatic redeployment whenever you push new commits to your linked branch.
Don't see your repository in the list?
Make sure you granted Render access to the correct repositories during the GitHub authorization step. You can fix permissions at github.com/apps/render/installations/new and select your repository under Repository access.
Help me connect my GitHub repository to Render.
Configure your Docker service
After clicking Connect, the service creation form appears. This is where you tell Render how to build and run your app.
- In the Language dropdown, select Docker.
- Choose the Free instance type.
- Expand the Advanced section at the bottom of the form.
- Under Environment Variables, click Add Environment Variable.
- Enter GEMINI_API_KEY in the Key field.
- Paste your actual Gemini API key in the Value field.
What happens when you set Language to Docker?
Render finds the Dockerfile in your repository root and uses it to build the image on every deploy. You do not need to set a build command or start command. Render reads both from your Dockerfile's instructions.
The environment variable you added is injected into the running container at runtime, just like when you used the -e flag with docker run locally.
Deploy and verify your live app
- Click Create Web Service at the bottom of the form.
Render starts building your Docker image. You can watch the build logs in real time on the Events page. The build typically takes 2-3 minutes.
Before you check your live URL, what do you think will happen when you open it? Will the app work the same as it did locally?
- Once the deploy status shows as live, find the .onrender.com URL at the top of your service page and click it.
- Verify the homepage loads in your browser.
- Test the AI feature by asking a DSA question through the app.
Your DSA assistant is now live on the internet. The homepage loads and the AI responds to questions, proving that both the container and the environment variable are working correctly in the cloud.
Why does the first request take a while?
Render's free tier spins down your service after 15 minutes of inactivity. The first request after sleeping takes 30-50 seconds while the container wakes up. Subsequent requests are fast.
Build failed or app crashes after deploy?
Check the build logs on the Events page for error messages. Common causes:
- If the log says it cannot find the Dockerfile, make sure your Dockerfile is committed to the root of your repository (not inside a subfolder).
- If the app crashes at startup, confirm your GEMINI_API_KEY environment variable is set correctly in the Render Dashboard under your service's Environment settings.
- If you see a port error, make sure your Dockerfile uses EXPOSE 10000 and Gunicorn binds to 0.0.0.0:10000. Render expects port 10000.
Help me debug my Render deploy failure.
Your app is live on the internet. Next up, you will push a code change and watch Render automatically redeploy it.
Ship a Change and Watch Auto-Deploy
Your app is live on the internet. Anyone with the URL can use your DSA assistant right now. But the real power of this setup is not just the initial deploy.
Professional teams ship code dozens of times a day without manually touching servers. They push code, the platform detects the change, rebuilds the container, and updates the live site automatically. This is CI/CD in action. In this step, you will experience that loop firsthand.
In this step, get ready to:
- Make a visible code change to your app.
- Commit and push to GitHub.
- Watch Render auto-deploy the update to your live URL.
Update your app's heading
To prove auto-deploy works, you need a change that is instantly visible when you load the page. A heading update is perfect for this.
- In your Antigravity IDE, open your main HTML template file (this is the template that renders your app's homepage).
- Find the heading text that displays your app's name. It might say something like DSA Learning Assistant.
- Change it to something noticeably different, for example DSA Learning Assistant v2 - Live!.
- Save the file.
Pick something obvious
Choose a change you will instantly recognise when you refresh your live URL. A subtle tweak like fixing a typo is easy to miss. A bold heading change makes it unmistakable that your auto-deploy worked.
Commit and push to GitHub
With your heading updated, you need to get that change into your GitHub repository. Render watches your repo for new commits and triggers a fresh deploy whenever one arrives.
- Stage, commit, and push your change by running these commands in your terminal:
git add .
git commit -m "Update heading to test auto-deploy"
git push
What do these commands do?
- git add . stages all changed files for commit.
- git commit -m "..." saves a snapshot of your changes with a descriptive message.
- git push sends that commit to your GitHub repository, which Render is watching.
You should see output confirming your push was successful, ending with a line showing your branch name.
Push rejected or failed?
- If you see a message about the remote containing work you don't have locally, run git pull --rebase first, then try git push again.
- If you see an authentication error, confirm your GitHub credentials are configured in your terminal.
Why is my git push failing?
Watch Render auto-deploy your change
The moment your push lands on GitHub, Render detects the new commit and starts building a fresh container from your updated code. You can watch this happen in real time.
- Switch back to the Render Dashboard in your browser.
- Click on your DSA assistant service.
- Click the Events tab.
Within seconds, a new deploy should appear as Build started. This confirms Render detected your push and is rebuilding your container automatically.
- Wait for the deploy to complete. This typically takes 1-2 minutes.
What is happening during the build?
Render is pulling your latest code from GitHub, running docker build using your Dockerfile, and replacing the running container with the newly built image. If the build fails, your existing version continues running so your app never goes offline.
Before you refresh your live URL, take a moment to predict. Do you think you will see your updated heading text, or the old version?
- Once the Events tab shows the deploy completed successfully, open your .onrender.com URL in your browser (or refresh it if you already have it open).
You should see your updated heading text displayed on the page. The change you made locally is now live on the internet, deployed automatically without you touching a server.
Still seeing the old heading?
- Make sure the deploy actually completed in the Events tab. If it still says in progress, wait for it to finish.
- Try a hard refresh in your browser: press Cmd+Shift+R (macOS) or Ctrl+Shift+R (Windows) to bypass the cache.
- Check that you actually saved the template file before committing. Open the file and confirm your heading change is there.
Why is my Render deploy not showing my code changes?
Secret mission
Add a Health Check Endpoint
Production apps need a way to tell the hosting platform they are alive and working. Right now, Render can only check if your port is open. In this secret mission, you will add a dedicated health check route and wire it into Render's monitoring so the platform knows your app logic is actually running.
Clean Up Your Resources
Clean Up Your Resources
Decide whether to keep your resources running, pause them to come back later, or delete them entirely. This project uses Render's free tier and local Docker images, so there are no ongoing costs.
Resources you used:
- Render Web Service (free tier). Runs your app in the cloud. The free tier sleeps after 15 minutes of inactivity and wakes on the next request with a 30-50 second cold start.
- Docker images on your local machine. Take up disk space but cost nothing.
Keep everything running
No action needed. Choose this if you are still actively building or want your app to stay live.
- Your app stays live at its .onrender.com URL.
- The free tier gives you 750 instance hours per month. That is more than enough for one service running 24/7.
- You will never be charged. No credit card is required for the free tier.
- Your Docker images remain on your local machine. They take up disk space but cost nothing.
Pause - I'll come back to this later
Shut down your cloud service to free up instance hours while keeping everything ready to resume.
- In the Render Dashboard, suspend your service to stop using instance hours. You can resume it anytime.
- Your GitHub repository and local code remain untouched.
- Your Docker images stay on your local machine until you manually remove them.
Delete - I don't want to use this again
Remove all project resources and start fresh. Your GitHub repository and local code remain untouched.
- In the Render Dashboard, go to your service Settings and click Delete Service at the bottom of the page.
- Remove the Docker image from your local machine by running this command in your terminal:
docker image rm dsa-assistant
This reclaims the disk space used by the container image.
That's a Wrap!
That's a Wrap!
Nice work! You just took a Flask app from "only works on my laptop" to live on the internet at a public URL that anyone can visit.
You've learned how to:
- Containerized a Python Flask app with Docker, writing a Dockerfile that packages your code, dependencies, and a production Gunicorn server into a portable image that runs identically anywhere.
- Managed secrets securely using environment variables passed at runtime, keeping your Gemini API key out of your code and Docker image entirely.
- Deployed your container to Render and experienced CI/CD firsthand. You pushed a code change to GitHub and watched it auto-deploy to your live URL within minutes.
- Secret Mission: Added a /health endpoint that Render uses to actively monitor your app's status, going beyond basic port checks.
Ready to quiz yourself?