Deploy GGCE with Docker
Let us guide you through the steps of configuring and deploying GGCE on your infrastructure.
Use the form below to generate customized instructions to set up your GGCE containers. It will create:
- A
ggce.ymlfile for use with docker compose - Customized instructions to test and troubleshoot GGCE containers
- Database instructions
Your customized GGCE docker configuration
docker compose is a convenient mechanism to configure containers. The configuration files use YAML syntax.
- Create a new folder called
ggceon your computer. - A common location is
C:\ggceon Windows. - Note: Use different folders for your production and test instances.
- In this folder create a blank file
ggce.ymlwith the contents as shown below. - Create a subfolder called
traefik. - The
ggce/traefikfolder will contain the reverse proxy configuration and SSL certificates. - Add
traefik.ymlanddynamic.ymlfiles to theggce/traefikfolder.
- ggce.yml
- traefik/traefik.yml
- traefik/dynamic.yml
# Standalone Docker compose file for GGCE
services:
ggce-api:
image: dockerhub.croptrust.org/grin-global/grin-global-server:2026.1.0
platform: linux/amd64
environment:
# GGCE URLs
SERVER_SERVLET_CONTEXT_PATH: /backend
BASE_URL: https://ggce.internal.lan/backend
BASE_URL_INTERNAL: http://localhost:8080/backend
FRONTEND_URL: https://ggce.internal.lan
# Database connection
DB_URL: jdbc:sqlserver://host.docker.internal:1433;DatabaseName=ggce;trustServerCertificate=true
DB_USERNAME: ggce
DB_PASSWORD: YourStrong@Passw0rd
## Configure the formatting of your accession numbers. Default is "PREFIX SEQUENTIAL SUFFIX" (with spaces).
## See https://ggce.genesys-pgr.org/docs/install/configuration/#accession-number-format and https://ggce.genesys-pgr.org/docs/install/configuration/#inventory-number-format
# Accession numbers look like "IG 123xxx"
# ACCESSION_FORMAT3: {0}
# Accession numbers look like "GBK-000123.xxx" (zero padded sequential number)
# ACCESSION_FORMAT2: -{0,number,000000}
# ACCESSION_FORMAT3: .{0}"
## For additional configuration options see https://ggce.genesys-pgr.org/docs/install/configuration/
# Advanced options
CACHE_LIBRARY: ehcache
volumes:
- ggce-data:/data/gringlobal
# ## Enable host.docker.internal on Linux
# extra_hosts:
# - "host.docker.internal:host-gateway"
networks:
default:
aliases:
- ggce-api
traefik: # Register the container on Traefik network
healthcheck:
test: [ "CMD", "curl", "-f", "http://localhost:8080/backend/robots.txt" ]
interval: 1m
timeout: 10s
retries: 5
start_period: 5m
deploy:
resources:
limits:
memory: 4g
restart: unless-stopped
labels:
traefik.enable: 'true'
traefik.http.middlewares.ggce-internal-lan-api-replacepathregex.replacePathRegex.regex: ^/(\.well-known/|api/|oauth2?/|GRINGlobal|sitemap.*xml)(.*)
traefik.http.middlewares.ggce-internal-lan-api-replacepathregex.replacePathRegex.replacement: "/backend/$$1$$2"
traefik.http.services.ggce-internal-lan-api.loadbalancer.server.port: 8080
traefik.http.services.ggce-internal-lan-api.loadbalancer.healthcheck.path: /backend/robots.txt
traefik.http.routers.ggce-internal-lan-api_http.entrypoints: http
traefik.http.routers.ggce-internal-lan-api_http.rule: (Host(`ggce.internal.lan`) && PathPrefix(`/backend/`)) || (Host(`ggce.internal.lan`) && PathRegexp(`^/(?:\.well-known/|api/|oauth2?/|GRINGlobal|sitemap.*xml)(:?.*)`))
traefik.http.routers.ggce-internal-lan-api_http.middlewares: ggce-internal-lan-api-replacepathregex@docker
# SSL handled by Traefik
traefik.http.middlewares.ggce-internal-lan-api-redirect-http.redirectscheme.scheme: https
traefik.http.routers.ggce-internal-lan-api.entrypoints: https
traefik.http.routers.ggce-internal-lan-api.tls: 'true'
traefik.http.routers.ggce-internal-lan-api.rule: (Host(`ggce.internal.lan`) && PathPrefix(`/backend/`)) || (Host(`ggce.internal.lan`) && PathRegexp(`^/(?:\.well-known/|api/|oauth2?/|GRINGlobal|sitemap.*xml)(:?.*)`))
traefik.http.routers.ggce-internal-lan-api.middlewares: ggce-internal-lan-api-replacepathregex@docker
ggce-ui:
image: dockerhub.croptrust.org/grin-global/grin-global-ui/gg-ce-web:2026.1.0
platform: linux/amd64
environment:
API_URL: https://ggce.internal.lan
API_URL_INTERNAL: http://ggce-api:8080/backend # This uses the internal network alias of the API service
FRONTEND_URL: https://ggce.internal.lan
NAME: Genebank Information System
NAME_SHORT: Demo
MENU_COLOR: '#683a29'
networks:
default:
traefik: # Register the container on Traefik network
depends_on:
ggce-api:
condition: service_healthy
deploy:
resources:
limits:
memory: 400m
restart: unless-stopped
labels:
traefik.enable: 'true'
traefik.http.services.ggce-internal-lan-ui.loadbalancer.server.port: 3000
traefik.http.services.ggce-internal-lan-ui.loadbalancer.healthcheck.path: /robots.txt
traefik.http.routers.ggce-internal-lan-ui_http.rule: Host(`ggce.internal.lan`)
traefik.http.routers.ggce-internal-lan-ui_http.entrypoints: http
# SSL handled by Traefik
traefik.http.middlewares.ggce-internal-lan-ui-redirect-http.redirectscheme.scheme: https
traefik.http.routers.ggce-internal-lan-ui.rule: Host(`ggce.internal.lan`)
traefik.http.routers.ggce-internal-lan-ui.entrypoints: https
traefik.http.routers.ggce-internal-lan-ui.tls: 'true'
reverse-proxy:
image: traefik:3.6.2
command:
- --configFile=/opt/traefik/traefik.yml
ports:
- "80:80" # Port for unencrypted HTTP traffic (can be disabled when https works)
- "443:443" # Port for encrypted traffic
# - "8080:8080" # Traefik's Web console
restart: unless-stopped
networks:
traefik: # Note the network name here must correspond with container labels "traefik.docker.network=traefik" above
volumes:
- /var/run/docker.sock:/var/run/docker.sock # So that Traefik can listen to the Docker events
- ./traefik/:/opt/traefik/ # Place traefik.yml and dynamic.yml into a subfolder called 'traefik'
volumes:
ggce-data:
external: true
networks:
traefik:
external: true # Please register a special network for Traefik: docker network create traefik
#
# This goes into traefik/traefik.yml
global:
checkNewVersion: false
sendAnonymousUsage: false
debug: true
log:
level: debug
# format: json
entryPoints:
http:
address: :80
proxyProtocol:
insecure: true
https:
address: :443
proxyProtocol:
insecure: true
tls:
providers:
providersThrottleDuration: 5s
docker:
exposedByDefault: false
network: traefik
file:
filename: /opt/traefik/dynamic.yml
watch: true
accessLog:
fields:
defaultMode: keep
headers:
defaultMode: keep
names:
Authorization: drop
Content-Type: keep
Cookie: drop
Set-Cookie: drop
api:
insecure: true
#
# This goes into traefik/dynamic.yml
tls:
stores:
default: {}
options:
default:
sniStrict: true
certificates:
- certFile: /opt/traefik/ggce-chain.crt
keyFile: /opt/traefik/ggce.key
On 10.11.0.1 create a docker network for Traefik:
# Create a docker network for Traefik
docker network create traefik
On 10.11.0.1 create a docker volume for GGCE. The volume is used for files that must be persisted even if the container is restarted.
# Create a docker volume for GGCE
docker volume create ggce-data
Start GGCE containers with docker compose:
# In the folder where you keep your ggce.yml file:
docker compose -f ggce.yml up -d
[+] Running 2/2
⠿ Container ggce-api-1 Healthy 90.8s
⠿ Container ggce-ui-1 Started 0.2s
When containers report a Healthy status you can connect to your GGCE.
To stop the containers use docker compose -f ggce.yml down.
Troubleshooting
Always check docker logs if GGCE is not working. In Docker Desktop click on the container name to see the logs. If using command line, then:
# Find the name of GGCE API
docker ps
# Print the logs
docker logs ggce-api
Inspect the logs and identify the problem. The most common is the connection to the database. Check your ggce.yml and update accordingly!
Keep a copy of your configuration
Make sure to keep a copy of your GGCE configuration in a safe place.