Skip to Content

Docker

Docker is a tool that allows you to package an application and its dependencies into a container that can run on any system. This makes it easy to deploy applications in a consistent and reproducible way, regardless of the underlying infrastructure.

To simplify running your GraphQL gateway, you can use the Docker image and the Docker Compose template we provide. This setup allows you to easily configure and run the gateway without the need to install Node.js and the required gateway npm packages.

Prerequisites

Make sure you have Docker installed on your system.

You can follow the official Docker Engine install manual in case you don’t have Docker installed already.

Configuration

Arguments

Hive Gateway can be configured with CLI arguments even when running the image!

For example, changing the supergraph to use the my-schema.graphql schema instead looks like this:

docker run \ -p 4000:4000 \ -v "$(pwd)/my-schema.graphql:/gateway/my-schema.graphql" \ ghcr.io/graphql-hive/gateway supergraph my-schema.graphql

For a full list of CLI arguments, please refer to the CLI arguments.

Config File

Instead of configuring Hive Gateway with CLI arguments, we support configuring with a config file.

You’re recommended to use the gateway.config.ts file to configure Hive Gateway. Simply mount the config file when running the image.

gateway.config.ts
import { defineConfig } from '@graphql-hive/gateway' export const gatewayConfig = defineConfig({ proxy: { endpoint: 'https://example.com/graphql' } })
docker run \ -p 4000:4000 \ -v "$(pwd)/gateway.config.ts:/gateway/gateway.config.ts" \ ghcr.io/graphql-hive/gateway proxy

For a full list of CLI arguments, please refer to the Config Reference.

Changing Port in Container

The default port where Hive Gateway listens is 4000; however, maybe the container is running inside a network (like when using Networking in Compose) and you wish to change the port of Hive Gateway in the image.

You can use the gateway.config.ts to change the port, or simply pass in the --port argument when running the image:

docker run \ -p 8080:8080 \ -v "$(pwd)/supergraph.graphql:/gateway/supergraph.graphql" \ ghcr.io/graphql-hive/gateway supergraph --port=8080

Running

Having a supergraph.graphql already composed with GraphQL Mesh, running the Docker image is as easy as:

docker run \ -p 4000:4000 \ -v "$(pwd)/supergraph.graphql:/gateway/gateway.config.ts" \ ghcr.io/graphql-hive/gateway supergraph

Docker Compose

You may have an environment where you want to use Docker Compose and would like to add Hive Gateway there.

Start by defining the docker-compose.yml

services: hive-gateway: image: ghcr.io/graphql-hive/gateway command: supergraph ports: - '4000:4000' # Add Hive Registry environment variables in case you use it # environment: # HIVE_CDN_ENDPOINT: <secret> # HIVE_CDN_KEY: <secret> # HIVE_REGISTRY_TOKEN: <secret> volumes: - ./gateway.config.ts:/gateway/gateway.config.ts

And then simply start the services with:

docker compose up

Extend Docker Image

Install Plugin

You may want to add additional functionality, or plugins to the base image - you just need to create a new Dockerfile basing the image off ghcr.io/graphql-hive/gateway.

If need only a handful of plugins (or some other dependencies), you can simply extend the image and install the modules with npm i:

For example, adding Block Field Suggestions Plugin to the container would look like this:

Dockerfile
FROM ghcr.io/graphql-hive/gateway RUN npm i @escape.tech/graphql-armor-block-field-suggestions
docker build -t hive-gateway-w-block-suggestions .

Configure to use the block field suggestions plugin:

gateway.config.ts
import { blockFieldSuggestionsPlugin } from '@escape.tech/graphql-armor-block-field-suggestions' import { defineConfig } from '@graphql-hive/gateway' export const gatewayConfig = defineConfig({ plugins: pluginCtx => [ blockFieldSuggestionsPlugin({ // Toggle the plugin | Default: true enabled: true, // Mask applied to the error message | default: '[Suggestion hidden]' mask: '[Suggestion hidden]' }) ] })

And then simply start the new image with the config file mounted:

docker run \ -p 4000:4000 \ -v "$(pwd)/gateway.config.ts:/gateway/gateway.config.ts" \ hive-gateway-w-block-suggestions supergraph

Develop Plugin

However, you may be developing a plugin and have a setup with some dependencies and source code, copying over your project’s files is the way to go.

In the following example, we’re developing a useTiming plugin that will add a human readable execution duration to the GraphQL result extensions property.

package.json
{ "name": "my-timing", "dependencies": { "moment": "^2" }, "devDependencies": { "@graphql-hive/gateway": "latest", "@graphql-hive/gateway": "latest" } }
my-timing.ts
import moment from 'moment' import type { GatewayPlugin } from '@graphql-hive/gateway' export function useTiming(): GatewayPlugin { return { onExecute() { const start = Date.now() return { onExecuteDone({ result, setResult }) { const duration = moment.duration(Date.now() - start) if (isAsyncIterable(result)) { setResult( mapAsyncIterator(result, result => ({ ...result, extensions: { ...result?.extensions, duration: duration.humanize() } })) ) return } setResult({ ...result, extensions: { ...result?.extensions, duration: duration.humanize() } }) } } } } }
gateway.config.ts
import { defineConfig } from '@graphql-hive/gateway' import { useTiming } from './my-timing' export const gatewayConfig = defineConfig({ plugins: () => [useTiming()] })

Your Dockerfile should then look something like this:

Dockerfile
FROM ghcr.io/graphql-hive/gateway # we dont install dev deps because: # 1. we need them for type checking only # 2. Hive Gateway is already available in the docker image COPY package*.json . RUN npm i --omit=dev COPY my-time.ts . COPY gateway.config.ts .

Then build your image:

docker build -t hive-gateway-w-my-timing .

And finally start it (the config file is in the image and doesn’t need to be mounted):

docker run -p 4000:4000 hive-gateway-w-my-timing supergraph
💡

For faster development, you can mount the source code as volumes so that you don’t have to rebuild the image on each run.

docker run -p 4000:4000 \ -v "$(pwd)/gateway.config.ts":/gateway/gateway.config.ts \ -v "$(pwd)/my-timing.ts":/gateway/my-timing.ts \ hive-gateway-w-my-timing supergraph

Additional Resolvers

Instead maybe you need to define additional resolvers that depend on other dependencies. Similarily to the Develop Plugin approach, you can just copy the project code over and build another image.

Say you have the following files:

package.json
{ "name": "my-time", "dependencies": { "moment": "^2" }, "devDependencies": { "@graphql-hive/gateway": "latest" } }
my-time.ts
import moment from 'moment' export const additionalResolvers = { Query: { formattedToday() { return moment().format('DD.MM.YYYY') } } }
gateway.config.ts
import { defineConfig } from '@graphql-hive/gateway' import { additionalResolvers } from './my-time' export const gatewayConfig = defineConfig({ additionalResolvers })

Your Dockerfile should then look something like this:

Dockerfile
FROM ghcr.io/graphql-hive/gateway # we dont install dev deps because: # 1. we need them for type checking only # 2. Hive Gateway is already available in the docker image COPY package*.json . RUN npm i --omit=dev COPY my-time.ts . COPY gateway.config.ts .

Then build your image:

docker build -t hive-gateway-w-add-res .

And finally start it (the config file is in the image and doesn’t need to be mounted):

docker run -p 4000:4000 hive-gateway-w-add-res supergraph

Known Security Vulnerabilities (affected CVE)

Security is important for us, and we are analysing on a regular bases our docker images against known CVE database using trivy.

Because it is based on the official Node image, which itself is based on official stable Debain image, our Node base image is affected by some CVE.

None of those CVE are affecting directly Hive Gateway software, since it doesn’t uses any of the affected components. But keep in mind that even if the gateway itself is not vulnerable, your own code can use affected components.

If you need a CVE free docker image, we recommend building your own image minimal image that exactly matches your needs.

Here is the list of CVE detected in our latest Node image (ghcr.io/graphql-hive/gateway:1.14.1):

PackageCVESeverityDescription
zlib1gCVE-2023-45853CRITICALMiniZip in zlib through 1.3 has an integer overflow and resultant heap-based buffer overflow in zipOpenNewFileInZip4_64 via a long filename, comment, or extra field. NOTE: MiniZip is not a supported part of the zlib product. NOTE: pyminizip through 0.2.6 is also vulnerable because it bundles an affected zlib version, and exposes the applicable MiniZip code through its compress API.
libldap-2.5-0CVE-2023-2953HIGHA vulnerability was found in openldap. This security flaw causes a null pointer dereference in ber_memalloc_x() function.
libldap-commonCVE-2023-2953HIGHA vulnerability was found in openldap. This security flaw causes a null pointer dereference in ber_memalloc_x() function.
perl-baseCVE-2023-31484HIGHCPAN.pm before 2.35 does not verify TLS certificates when downloading distributions over HTTPS.
krb5-localesCVE-2025-3576MEDIUMA vulnerability in the MIT Kerberos implementation allows GSSAPI-protected messages using RC4-HMAC-MD5 to be spoofed due to weaknesses in the MD5 checksum design. If RC4 is preferred over stronger encryption types, an attacker could exploit MD5 collisions to forge message integrity codes. This may lead to unauthorized message tampering.
libgssapi-krb5-2CVE-2025-3576MEDIUMA vulnerability in the MIT Kerberos implementation allows GSSAPI-protected messages using RC4-HMAC-MD5 to be spoofed due to weaknesses in the MD5 checksum design. If RC4 is preferred over stronger encryption types, an attacker could exploit MD5 collisions to forge message integrity codes. This may lead to unauthorized message tampering.
libk5crypto3CVE-2025-3576MEDIUMA vulnerability in the MIT Kerberos implementation allows GSSAPI-protected messages using RC4-HMAC-MD5 to be spoofed due to weaknesses in the MD5 checksum design. If RC4 is preferred over stronger encryption types, an attacker could exploit MD5 collisions to forge message integrity codes. This may lead to unauthorized message tampering.
libkrb5-3CVE-2025-3576MEDIUMA vulnerability in the MIT Kerberos implementation allows GSSAPI-protected messages using RC4-HMAC-MD5 to be spoofed due to weaknesses in the MD5 checksum design. If RC4 is preferred over stronger encryption types, an attacker could exploit MD5 collisions to forge message integrity codes. This may lead to unauthorized message tampering.
libkrb5support0CVE-2025-3576MEDIUMA vulnerability in the MIT Kerberos implementation allows GSSAPI-protected messages using RC4-HMAC-MD5 to be spoofed due to weaknesses in the MD5 checksum design. If RC4 is preferred over stronger encryption types, an attacker could exploit MD5 collisions to forge message integrity codes. This may lead to unauthorized message tampering.
libpam-modulesCVE-2024-10041MEDIUMA vulnerability was found in PAM. The secret information is stored in memory, where the attacker can trigger the victim program to execute by sending characters to its standard input (stdin). As this occurs, the attacker can train the branch predictor to execute an ROP chain speculatively. This flaw could result in leaked passwords, such as those found in /etc/shadow while performing authentications.
libpam-modulesCVE-2024-22365MEDIUMlinux-pam (aka Linux PAM) before 1.6.0 allows attackers to cause a denial of service (blocked login process) via mkfifo because the openat call (for protect_dir) lacks O_DIRECTORY.
libpam-modules-binCVE-2024-10041MEDIUMA vulnerability was found in PAM. The secret information is stored in memory, where the attacker can trigger the victim program to execute by sending characters to its standard input (stdin). As this occurs, the attacker can train the branch predictor to execute an ROP chain speculatively. This flaw could result in leaked passwords, such as those found in /etc/shadow while performing authentications.
libpam-modules-binCVE-2024-22365MEDIUMlinux-pam (aka Linux PAM) before 1.6.0 allows attackers to cause a denial of service (blocked login process) via mkfifo because the openat call (for protect_dir) lacks O_DIRECTORY.
libpam-runtimeCVE-2024-10041MEDIUMA vulnerability was found in PAM. The secret information is stored in memory, where the attacker can trigger the victim program to execute by sending characters to its standard input (stdin). As this occurs, the attacker can train the branch predictor to execute an ROP chain speculatively. This flaw could result in leaked passwords, such as those found in /etc/shadow while performing authentications.
libpam-runtimeCVE-2024-22365MEDIUMlinux-pam (aka Linux PAM) before 1.6.0 allows attackers to cause a denial of service (blocked login process) via mkfifo because the openat call (for protect_dir) lacks O_DIRECTORY.
libpam0gCVE-2024-10041MEDIUMA vulnerability was found in PAM. The secret information is stored in memory, where the attacker can trigger the victim program to execute by sending characters to its standard input (stdin). As this occurs, the attacker can train the branch predictor to execute an ROP chain speculatively. This flaw could result in leaked passwords, such as those found in /etc/shadow while performing authentications.
libpam0gCVE-2024-22365MEDIUMlinux-pam (aka Linux PAM) before 1.6.0 allows attackers to cause a denial of service (blocked login process) via mkfifo because the openat call (for protect_dir) lacks O_DIRECTORY.
libtinfo6CVE-2023-50495MEDIUMNCurse v6.4-20230418 was discovered to contain a segmentation fault via the component _nc_wrap_entry().
ncurses-baseCVE-2023-50495MEDIUMNCurse v6.4-20230418 was discovered to contain a segmentation fault via the component _nc_wrap_entry().
ncurses-binCVE-2023-50495MEDIUMNCurse v6.4-20230418 was discovered to contain a segmentation fault via the component _nc_wrap_entry().
wgetCVE-2021-31879MEDIUMGNU Wget through 1.21.1 does not omit the Authorization header upon a redirect to a different origin, a related issue to CVE-2018-1000007.
wgetCVE-2024-10524MEDIUMApplications that use Wget to access a remote resource using shorthand URLs and pass arbitrary user credentials in the URL are vulnerable. In these cases attackers can enter crafted credentials which will cause Wget to access an arbitrary host.
Last updated on