On this page
Docker deployment
This guide runs TGateway directly on a Linux Docker host, without Watchdog. Build an image from the complete linux-x64 release. The reference image in Downloads is for linux-x64 evaluation. ARM64 requires a matching package, base image, and build platform.
Prepare the release directory
Use GatewayApp from the complete platform-matching Watchdog package, or a complete TGateway release for that platform. Do not copy only the executable or use an unpublished source tree as the runtime build context.
The directory must contain TGateway, appsettings.json, Configuration/, and bundled dependencies. Separate programs from project data:
| Container path | Purpose |
|---|---|
/app | Programs and dependencies from the current image, replaced on image update |
/data | Project configuration, databases, logs, cache, scripts, user plugins, and certificates in a persistent volume |
ProjectDirectory=/data | Tells TGateway where to load business configuration and store project data |
See project directory configuration. Absolute paths outside that directory need their own mounts.
Build the image
Save the following Dockerfile in the complete release directory. Docker seeds a newly created empty named volume from the image; an existing volume retains its contents.
FROM mcr.microsoft.com/dotnet/runtime:10.0-noble-amd64
WORKDIR /app
COPY . /app
# 工程与程序分离,首次空卷获得配置和随包工程资源。
RUN chmod +x /app/TGateway \
&& mkdir -p /data \
&& cp /app/appsettings.json /data/appsettings.json \
&& for directory in Configuration DB OTHERDB opc ScriptDlls CustomNodeDlls PluginDlls RuntimeDlls public data files; do \
if [ -d "/app/$directory" ]; then cp -a "/app/$directory" "/data/$directory"; fi; \
done
ENV TZ=Asia/Shanghai
ENV ProjectDirectory=/data
EXPOSE 6100
ENTRYPOINT ["/app/TGateway"]docker build --platform linux/amd64 -t my-tgateway:current .
docker volume create tgateway-project
docker run -d --name tgateway --restart unless-stopped \
--mount type=volume,source=tgateway-project,target=/data \
-p 127.0.0.1:6100:6100 \
my-tgateway:currentThe example exposes management only on the host loopback address. Open http://localhost:6100 on that host; arrange an HTTPS proxy for remote access. Follow TGateway sign-in for credentials and workspace checks.
Do not mount an old program directory over /app: that can hide programs from a newer image. With a bind mount instead of a named volume, prepare the complete project configuration and permissions yourself; Docker does not seed an empty bind directory from the image.
Check runtime and networking
docker ps --filter name=tgateway
docker logs --tail 100 tgateway
docker inspect --format '{{json .Mounts}}' tgatewayConfirm that the container stays running, /data uses the intended volume, and Web sign-in works. Then read a known simulator point and verify data independently at the real destination.
127.0.0.1inside the container refers to the container itself. Use a reachable address for the host or an external device.- Client drivers connecting to equipment normally do not require published device ports. Publish ports when a simulator or protocol server accepts external connections; specify
/udpfor UDP. - Serial use requires the actual
--devicemapping and account permissions. Discovery and broadcast protocols also require appropriate Docker networking. - Default business logs are inside project
Logs/. Check external databases, upload paths, and absolute history paths separately.
Verify persistence
- Save a recognizable test variable name or description and record the current Gateway code.
- Stop and remove the container in a test or maintenance window; collection in that container is interrupted.
- Recreate it with the same image and the same
tgateway-projectvolume:
docker stop tgateway
docker rm tgateway
docker run -d --name tgateway --restart unless-stopped \
--mount type=volume,source=tgateway-project,target=/data \
-p 127.0.0.1:6100:6100 \
my-tgateway:current- Sign in again. Check project configuration, Gateway code, retained records, and new samples. A simple
docker restartdoes not prove recovery after container removal.
Do not remove the data volume to repair configuration or license-state parsing errors. See invalid license-state files.
Back up and update
Build my-tgateway:next from the new complete release, then arrange a maintenance window. Stop the container before backup so committed SQLite WAL data is not omitted by copying only a live main database file:
docker stop tgateway
mkdir -p backups
docker run --rm \
--mount type=volume,source=tgateway-project,target=/data,readonly \
--mount type=bind,source="$(pwd)/backups",target=/backup \
--entrypoint sh my-tgateway:current \
-c 'tar -C /data -czf /backup/gateway-project-before-update.tar.gz .'Confirm that the archive exists and can be extracted. Remove the old container, reuse the original volume with the run command above, and change the image to my-tgateway:next. Existing volumes do not automatically receive new initial configuration from an image. Apply release-specific configuration changes while preserving site databases, identity, and user resources.
After updating, check version, project, known samples, forwarding, and history queries. For data recovery, stop the new container and preserve the current volume before restoring the complete project backup. Retain the original image together with its matching data backup.
Common problems
| Symptom | Check and recovery |
|---|---|
| Restart loop | Read docker logs; check architecture, executable permissions, and project configuration |
| Web works but device requests time out | Check routes from the container; do not use its own localhost for the host |
| Points or identity lost after recreation | Check volume reuse, ProjectDirectory, and external absolute paths |
| Database or log creation fails | Check volume permissions and container account |
| Old version after image replacement | Check the image tag and any old directory mounted over /app |