Docker
Many cloud providers support running Docker containers. Thus, Exograph can be deployed through Docker. This document provides instructions on performing specific tasks and running an Exograph server locally for development using Docker.
Exograph explicitly supports running a server in Fly.io and Railway. While the underlying mechanism uses Docker, you should follow the specific deployment guides for these providers.
Exograph does not use a Docker container for AWS Lambda or Cloudflare Workers. To deploy in those environments, please follow the AWS Lambda or Cloudflare Workers guides.
Exograph provides three Docker images:
ghcr.io/exograph/cli: It includes only theexoCLI and may be used for development tasks such as building theexo_irfile and computing the database schema. Note that you cannot runexo yoloorexo devusing this image (you can useghcr.io/exograph/devfor this purpose).ghcr.io/exograph/server: It includes only the Exograph server and forms the basis for running it in production.ghcr.io/exograph/dev: It includes the Exograph server, theexoCLI, and Postgres 16. Since it is optimized for development, it is a rather large image, and it is not recommended for production use. Typically, you will enter into a shell for this image to perform development tasks, includingexo yoloandexo dev.
Let's see how you can use these images for specific tasks.
Building the exo_ir file
To run an Exograph server, you must build an exo_ir file. While you would typically build this file using the build command to use the locally installed exo CLI, you can also build this file using a Docker container using the ghcr.io/exograph/cli image (you may also use ghcr.io/exograph/dev).
docker run --rm --platform linux/x86_64 \
--mount type=bind,source="$(pwd)",target=/usr/src/app \
-it ghcr.io/exograph/cli:latest bash -c "exo build"
This will build the exo_ir file and put it in the target directory.
Running the server
To run the server locally, you will need to pass the Postgres connection URL such that the Docker container can resolve it.
docker run --rm --platform linux/x86_64 \
--mount type=bind,source="$(pwd)",target=/usr/src/app \
-e EXO_POSTGRES_URL=<postgres-url> \
-e EXO_INTROSPECTION=true \
-p 9876:9876 \
-it ghcr.io/exograph/dev:latest exo-server
The URL form will depend on the database you are using.
- Cloud database: If you use a cloud Postgres database such as Neon, simply pass the connection URL given to you by the database provider.
- Local database: If you use a local Postgres database, you may use
host.docker.internalas the host since this is a special DNS name that resolves to the host machine. That URL will be of the formpostgres://<user>:<password>@host.docker.internal:5432/<database>.
You may pass any additional environment such as EXO_JWT_SECRET and EXO_OIDC_URL to configure authentication and EXO_INTROSPECTION to enable introspection, etc.
Building a Docker image
If you need a generic (cloud-provider-agnostic) Docker image for your application, you can start with the following Dockerfile:
FROM ghcr.io/exograph/cli:latest as builder
WORKDIR /app
COPY ./src ./src
# In some setups, we need to run `exo build` as root (otherwise, we get permission errors)
USER root
RUN exo build
# You may add additional build steps such as
# `RUN exo schema migrate` to run migrations automatically.
FROM ghcr.io/exograph/server:latest
WORKDIR /app
COPY /app/target/index.exo_ir ./target/index.exo_ir
# You may pass additional environment variables to the server in the following line.
CMD ["sh", "-c", "EXO_POSTGRES_URL=$EXO_POSTGRES_URL exo-server"]
Notice how we use a multi-stage build to first build the exo_ir file using the ghcr.io/exograph/cli image and then copy it into the ghcr.io/exograph/server image.
You can then build the Docker container using:
docker build -t todo-api .
You can then run the Docker container using:
docker run \
--platform linux/x86_64 \
--name todo-api \
-e EXO_POSTGRES_URL=<postgres-url> \
-e EXO_SERVER_HOST=0.0.0.0 \
-p 9876:9876 \
-d todo-api
You must pass -e EXO_SERVER_HOST=0.0.0.0 since the container needs to bind to all network interfaces.
Of course, you may pass any additional environment such as EXO_JWT_SECRET and EXO_OIDC_URL to configure authentication and EXO_INTROSPECTION to enable introspection, etc.
Note the use of -d to run the container in detached mode. It will free up the terminal for you to continue using. If you need to go into the container, you can use docker exec -it todo-api bash and if you need to stop it, you can use docker stop todo-api.