How to Set Up an Astro Website using Podman Containers

Mar 30, 2025 10 min

Over the past couple years, containers have become my preferred method for developing applications, APIs, and websites. Podman containers offer a straightforward and efficient way to create isolated, consistent environments.

Here’s a few of the reasons I enjoy using Podman for development:

  • Consistency and Isolation: Containers create a predictable environment by isolating dependencies, ensuring my local setup mirrors the production environment.
  • Versioned Artifacts: I utilize a CI/CD pipeline to publish apps, APIs, and websites; containers make it easy to generate versioned artifacts for easy tracking and management.
  • Simplified Development Workflow: It streamlines moving from local development to production, avoiding common pitfalls related to running code in different environments.

Admittedly, developing Astro websites with containers is somewhat of a niche interest (hence the limited documentation available). However, I put together this guide to help readers who might be interested in this approach given the benefits of container development and deployment.

In this post, I’ll demonstrate how to set up an Astro project locally, then containerize it using Podman.

Note: This guide is valid for both Podman and Docker, just replace ‘podman’ for ‘docker’ for the commands. The instructions included here use Podman because it’s my preferred platform, but you can use whichever container platform suits you best.

Initializing Astro Locally

First, initialize your Astro project locally:

npm create astro@latest

You can also initialize your Astro project using a template like the blog template to help you get started:

npm create astro@latest . -- --template blog --install

If you want additional dependencies like Tailwind CSS, install them locally:

npm install tailwindcss @tailwindcss/vite

Note: If you’d prefer bootstrapping Astro entirely within a container, run:

podman run -it --rm -v "${PWD}":/app:Z -w /app docker.io/library/node:22.14-alpine3.21 npm create astro@latest . -- --template blog --install

Then, add dependencies similarly within the container:

podman run -it --rm -v "${PWD}":/app:Z -w /app docker.io/library/node:22.14-alpine3.21 npm install tailwindcss @tailwindcss/vite 

One of the benefits of this approach is that it’s not necessary to install Node.js locally because you can use Node.js within the container to install your dependencies.

Preparing the Container for Build

Include a .dockerignore or .containerignore file before building your container.

At minimum, include:

# dependencies
node_modules/

# build output
dist/

Review your project directory and add any other files you’d like to leave out of your container build (like static images and videos).

Building the Container

Here’s a simple Containerfile example for creating an Astro website container:

# Use Alpine Linux for a smaller container size
FROM docker.io/node:22.14-alpine3.21

WORKDIR /app
COPY package*.json ./

RUN npm install
RUN npx astro telemetry disable

COPY . .

ENV HOST=0.0.0.0
ENV PORT=4321

EXPOSE 4321

CMD ["npm", "run", "dev", "--", "--host"]

Note: To access your Astro container from the host, you must use the --host flag, as shown above. Another option is to update your package.json scripts to:

"dev": "astro dev --host",
"preview": "astro preview --host"

Then your Containerfile would simply use:

CMD ["npm", "run", "dev"]

Instead of the CMD ["npm", "run", "dev", "--", "--host"] shown above.

In this example, I used the Alpine Linux image for the container to significantly reduce the image size, improving build and deployment times.

For consistent builds, especially in CI/CD environments, you should consider using “npm ci” instead of “npm install” in your container builds. Also, for production deployments, it’s recommended to build static assets using “npm run build” (“astro build”) and serve them with a production-ready web server, such as nginx, instead of running the development server (“npm run dev”).

Finally, build the container using:

podman build . -f Containerfile -t localhost/astro-podman-website:latest

The tag “latest” is used here for demonstration purposes, but you should ideally use semantic versioning tags (e.g., localhost/astro-podman-website:1.0.0) to manage container versions clearly.

Running the Container

To run your Astro container, use the following command:

podman run -d --name astro-podman-website -p 4321:4321 -v "${PWD}":/app:Z localhost/astro-podman-website:latest

Your Astro website will be available on localhost:4321.

A couple notes on this “podman run” command:

  • The volume mount (-v ”${PWD}”:/app:Z) links your local project directory directly to the container’s /app directory. This setup ensures any changes you make locally are immediately reflected inside the running container, eliminating the need to rebuild the container each time. This greatly speeds up the development cycle and simplifies testing changes.
  • The “:Z” tag at the end of the volume mount helps with permission or SELinux issues with Podman by addressing SELinux contexts.

If you encounter any issues running the container, you can inspect the container by viewing its logs (“podman logs astro-podman-website”), or by entering the container’s shell to debug issues (“podman exec -it astro-podman-website /bin/sh”).

Once you are done, run the commands “podman stop astro-podman” and then “podman rm astro-podman” to stop and remove the container.

Closing Thoughts

Deploying your Astro website using Podman containers can make your workflow more efficient by providing a seamless way to manage your development and production environments. Hopefully you found this guide helpful and are able to use this approach in your own projects.

~Scott Burton