# Directus Dockerfile Generator

URL: /dockerizer/directus

Generate a Dockerfile that extends the official Directus image with your own extensions and snapshot, rather than rebuilding Directus from source.

## Default configuration

- `appName` (App name): directus — Used for the image tag, the compose service and the OCI labels.

- `port` (Port): 8055 — The port the app listens on inside the container. Keep it above 1024 so the process can bind it without root.

- `directusVersion` (Directus version): 11

- `extensionsDir` (Extensions directory): extensions — Built extensions are copied into the image. Leave the folder empty if you have none.

- `database` (Database service): none — Adds the database to docker-compose.yml with a healthcheck, a named volume and a DATABASE_URL wired into the app.

- `redis` (Redis service): false — Adds Redis to docker-compose.yml and exposes REDIS_URL to the app.

- `multiArch` (Multi-architecture build): false — Adds BUILDPLATFORM/TARGETARCH so `docker buildx build --platform linux/amd64,linux/arm64` cross-compiles natively.

- `healthcheck` (Healthcheck): true — Adds a HEALTHCHECK so orchestrators can restart an unresponsive container.

- `ociLabels` (OCI labels): false — Adds org.opencontainers.image.* metadata to the final image.

## Generated files

### Dockerfile

Multi-stage build: dependencies, compilation and the runtime image are separate, so only what the app needs at runtime ships.

```docker
# syntax=docker/dockerfile:1
# Generated by Easypanel Dockerizer — https://easypanel.io/dockerizer

# --- Runtime ------------------------------------------

# Directus is distributed as a finished image. Extending it is the supported path — rebuilding from source is not.
FROM directus/directus:11
ENV PORT=8055
ENV PUBLIC_URL=http://localhost:8055

# Your compiled extensions. Remove this line if you have none.
COPY --chown=node:node extensions/ /directus/extensions/
USER node
EXPOSE 8055
STOPSIGNAL SIGTERM

# Lets Docker, Compose and Easypanel see when the app is wedged
HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --retries=3 \
  CMD ["node", "-e", "fetch('http://127.0.0.1:8055/server/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"]

```

### .dockerignore

Keeps the build context small and stops secrets and local dependencies from reaching an image layer.

```bash
# Version control
.git
.gitignore
.github

# Secrets — never bake these into an image layer
.env
.env.*
!.env.example
*.pem
*.key

# Editor and OS noise
.vscode
.idea
.DS_Store
Thumbs.db

# Docs and local tooling
README.md
LICENSE
docs
.editorconfig
docker-compose*.yml
Dockerfile*
.dockerignore

# Only built extensions are copied in
node_modules
**/node_modules
uploads
database

```

### docker-compose.yml

Runs the image locally with its backing services, wired together and health-gated.

```yaml
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    restart: unless-stopped
    ports:
      - "8055:8055"
    environment:
      SECRET: replace-me
      ADMIN_EMAIL: admin@example.com
      ADMIN_PASSWORD: replace-me
    volumes:
      - directus-uploads:/directus/uploads

```

## Frequently asked questions

### Why not build Directus from source?

There is no benefit. Directus publishes a maintained image; extending it means you get upstream fixes by bumping one tag instead of maintaining a build.

### How do I add a database?

Pick one in the database field above. Directus reads DB_CLIENT and the connection details from the environment — the generated compose file wires PostgreSQL or MySQL up with a healthcheck.

## Related generators

- [Strapi](/dockerizer/strapi)

- [Payload CMS](/dockerizer/payload)

- [Medusa](/dockerizer/medusa)

- [Node.js](/dockerizer/nodejs)