Server Agent - Docker
Install the ByteHide Server Agent inside Docker containers for zero-code runtime protection. The agent is installed at image build time and protects all .NET 6+ processes in the container.
Key Difference vs Bare Metal
On a normal server, you run the installer once and it persists permanently. In Docker, the install happens at image build time, and you need to explicitly load the environment variables because Docker doesn't source /etc/profile.d/ or read the Windows Registry at runtime.
Linux Containers
Shell Script (No SDK Needed in Runtime Image)
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY . .
RUN dotnet publish -c Release -o /app
FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /app
COPY /app .
# Install ByteHide Agent
RUN apt-get update && apt-get install -y --no-install-recommends curl ca-certificates \
&& rm -rf /var/lib/apt/lists/* \
&& curl -sSL https://raw.githubusercontent.com/bytehide/monitor-dotnet-agent/main/install.sh \
| bash -s -- --token <your-token>
# Docker doesn't source /etc/profile.d/, so load env vars in entrypoint
ENTRYPOINT ["/bin/bash", "-c", "source /etc/profile.d/bytehide-agent.sh && exec dotnet myapp.dll"]FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY . .
RUN dotnet publish -c Release -o /app
FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /app
COPY /app .
# Install ByteHide Agent
RUN apt-get update && apt-get install -y --no-install-recommends curl ca-certificates \
&& rm -rf /var/lib/apt/lists/* \
&& curl -sSL https://raw.githubusercontent.com/bytehide/monitor-dotnet-agent/main/install.sh \
| bash -s -- --token <your-token>
# Docker doesn't source /etc/profile.d/, so load env vars in entrypoint
ENTRYPOINT ["/bin/bash", "-c", "source /etc/profile.d/bytehide-agent.sh && exec dotnet myapp.dll"]dotnet tool (If SDK Available in Build Stage)
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY . .
RUN dotnet publish -c Release -o /app
# Install agent in the build stage (has SDK)
RUN dotnet tool install -g Bytehide.Monitor.AgentCli --version 1.0.5 \
&& /root/.dotnet/tools/bytehide-agent install --token <your-token>
FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /app
COPY /app .
# Copy agent files from build stage
COPY /opt/bytehide/agent /opt/bytehide/agent
COPY /etc/profile.d/bytehide-agent.sh /etc/profile.d/bytehide-agent.sh
ENTRYPOINT ["/bin/bash", "-c", "source /etc/profile.d/bytehide-agent.sh && exec dotnet myapp.dll"]FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY . .
RUN dotnet publish -c Release -o /app
# Install agent in the build stage (has SDK)
RUN dotnet tool install -g Bytehide.Monitor.AgentCli --version 1.0.5 \
&& /root/.dotnet/tools/bytehide-agent install --token <your-token>
FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /app
COPY /app .
# Copy agent files from build stage
COPY /opt/bytehide/agent /opt/bytehide/agent
COPY /etc/profile.d/bytehide-agent.sh /etc/profile.d/bytehide-agent.sh
ENTRYPOINT ["/bin/bash", "-c", "source /etc/profile.d/bytehide-agent.sh && exec dotnet myapp.dll"]Alpine Linux
The installer auto-detects musl/Alpine. The only difference is using apk instead of apt:
FROM mcr.microsoft.com/dotnet/aspnet:8.0-alpine
WORKDIR /app
COPY /app .
RUN apk add --no-cache curl bash \
&& curl -sSL https://raw.githubusercontent.com/bytehide/monitor-dotnet-agent/main/install.sh \
| bash -s -- --token <your-token>
ENTRYPOINT ["/bin/bash", "-c", "source /etc/profile.d/bytehide-agent.sh && exec dotnet myapp.dll"]FROM mcr.microsoft.com/dotnet/aspnet:8.0-alpine
WORKDIR /app
COPY /app .
RUN apk add --no-cache curl bash \
&& curl -sSL https://raw.githubusercontent.com/bytehide/monitor-dotnet-agent/main/install.sh \
| bash -s -- --token <your-token>
ENTRYPOINT ["/bin/bash", "-c", "source /etc/profile.d/bytehide-agent.sh && exec dotnet myapp.dll"]Windows Containers
Windows Server Core
FROM mcr.microsoft.com/dotnet/sdk:8.0-windowsservercore-ltsc2022 AS build
WORKDIR /src
COPY . .
RUN dotnet publish -c Release -o /app
FROM mcr.microsoft.com/dotnet/aspnet:8.0-windowsservercore-ltsc2022
WORKDIR /app
COPY /app .
# Install ByteHide Agent
SHELL ["powershell", "-Command"]
RUN & ([scriptblock]::Create((Invoke-WebRequest -Uri 'https://raw.githubusercontent.com/bytehide/monitor-dotnet-agent/main/install.ps1' -UseBasicParsing).Content)) -Token '<your-token>'
# Docker doesn't propagate Registry changes to runtime. Set env vars explicitly:
ENV DOTNET_STARTUP_HOOKS="C:\\Program Files\\ByteHide\\Agent\\Bytehide.Monitor.ServerAgent.dll"
ENV ASPNETCORE_HOSTINGSTARTUPASSEMBLIES="Bytehide.Monitor.ServerAgent"
ENV BYTEHIDE_MONITOR_TOKEN="<your-token>"
ENV BYTEHIDE_MONITOR_CONFIG="C:\\Program Files\\ByteHide\\Agent\\monitor.config.json"
ENTRYPOINT ["dotnet", "myapp.dll"]FROM mcr.microsoft.com/dotnet/sdk:8.0-windowsservercore-ltsc2022 AS build
WORKDIR /src
COPY . .
RUN dotnet publish -c Release -o /app
FROM mcr.microsoft.com/dotnet/aspnet:8.0-windowsservercore-ltsc2022
WORKDIR /app
COPY /app .
# Install ByteHide Agent
SHELL ["powershell", "-Command"]
RUN & ([scriptblock]::Create((Invoke-WebRequest -Uri 'https://raw.githubusercontent.com/bytehide/monitor-dotnet-agent/main/install.ps1' -UseBasicParsing).Content)) -Token '<your-token>'
# Docker doesn't propagate Registry changes to runtime. Set env vars explicitly:
ENV DOTNET_STARTUP_HOOKS="C:\\Program Files\\ByteHide\\Agent\\Bytehide.Monitor.ServerAgent.dll"
ENV ASPNETCORE_HOSTINGSTARTUPASSEMBLIES="Bytehide.Monitor.ServerAgent"
ENV BYTEHIDE_MONITOR_TOKEN="<your-token>"
ENV BYTEHIDE_MONITOR_CONFIG="C:\\Program Files\\ByteHide\\Agent\\monitor.config.json"
ENTRYPOINT ["dotnet", "myapp.dll"]Windows Nano Server
Nano Server doesn't have PowerShell by default. Use the dotnet tool approach in a multi-stage build:
FROM mcr.microsoft.com/dotnet/sdk:8.0-nanoserver-ltsc2022 AS build
WORKDIR /src
COPY . .
RUN dotnet publish -c Release -o /app
# Install agent (SDK available in build stage)
RUN dotnet tool install -g Bytehide.Monitor.AgentCli --version 1.0.5
RUN bytehide-agent install --token <your-token>
FROM mcr.microsoft.com/dotnet/aspnet:8.0-nanoserver-ltsc2022
WORKDIR /app
COPY /app .
# Copy agent DLLs from build stage
COPY ["C:/Program Files/ByteHide/Agent", "C:/Program Files/ByteHide/Agent"]
ENV DOTNET_STARTUP_HOOKS="C:\\Program Files\\ByteHide\\Agent\\Bytehide.Monitor.ServerAgent.dll"
ENV ASPNETCORE_HOSTINGSTARTUPASSEMBLIES="Bytehide.Monitor.ServerAgent"
ENV BYTEHIDE_MONITOR_TOKEN="<your-token>"
ENV BYTEHIDE_MONITOR_CONFIG="C:\\Program Files\\ByteHide\\Agent\\monitor.config.json"
ENTRYPOINT ["dotnet", "myapp.dll"]FROM mcr.microsoft.com/dotnet/sdk:8.0-nanoserver-ltsc2022 AS build
WORKDIR /src
COPY . .
RUN dotnet publish -c Release -o /app
# Install agent (SDK available in build stage)
RUN dotnet tool install -g Bytehide.Monitor.AgentCli --version 1.0.5
RUN bytehide-agent install --token <your-token>
FROM mcr.microsoft.com/dotnet/aspnet:8.0-nanoserver-ltsc2022
WORKDIR /app
COPY /app .
# Copy agent DLLs from build stage
COPY ["C:/Program Files/ByteHide/Agent", "C:/Program Files/ByteHide/Agent"]
ENV DOTNET_STARTUP_HOOKS="C:\\Program Files\\ByteHide\\Agent\\Bytehide.Monitor.ServerAgent.dll"
ENV ASPNETCORE_HOSTINGSTARTUPASSEMBLIES="Bytehide.Monitor.ServerAgent"
ENV BYTEHIDE_MONITOR_TOKEN="<your-token>"
ENV BYTEHIDE_MONITOR_CONFIG="C:\\Program Files\\ByteHide\\Agent\\monitor.config.json"
ENTRYPOINT ["dotnet", "myapp.dll"]Docker Compose
Environment Variables via .env File
Instead of hardcoding the token in the Dockerfile, use Docker Compose with an env file:
docker-compose.yml:
services:
myapp:
build: .
env_file:
- bytehide.env
ports:
- "8080:8080"services:
myapp:
build: .
env_file:
- bytehide.env
ports:
- "8080:8080"bytehide.env:
DOTNET_STARTUP_HOOKS=/opt/bytehide/agent/Bytehide.Monitor.ServerAgent.dll
ASPNETCORE_HOSTINGSTARTUPASSEMBLIES=Bytehide.Monitor.ServerAgent
BYTEHIDE_MONITOR_TOKEN=bh_xxxxxxxxxxxx
BYTEHIDE_MONITOR_CONFIG=/opt/bytehide/agent/monitor.config.jsonDOTNET_STARTUP_HOOKS=/opt/bytehide/agent/Bytehide.Monitor.ServerAgent.dll
ASPNETCORE_HOSTINGSTARTUPASSEMBLIES=Bytehide.Monitor.ServerAgent
BYTEHIDE_MONITOR_TOKEN=bh_xxxxxxxxxxxx
BYTEHIDE_MONITOR_CONFIG=/opt/bytehide/agent/monitor.config.jsonThis way the Dockerfile only installs the agent files, and the environment variables come from Compose. Useful when the token differs per environment (staging, production).
Build Arguments for Tokens
Avoid hardcoding tokens in the Dockerfile:
ARG BYTEHIDE_TOKEN
RUN curl -sSL https://raw.githubusercontent.com/bytehide/monitor-dotnet-agent/main/install.sh \
| bash -s -- --token ${BYTEHIDE_TOKEN}ARG BYTEHIDE_TOKEN
RUN curl -sSL https://raw.githubusercontent.com/bytehide/monitor-dotnet-agent/main/install.sh \
| bash -s -- --token ${BYTEHIDE_TOKEN}Build with:
docker build --build-arg BYTEHIDE_TOKEN=bh_xxxxxxxxxxxx -t myapp .docker build --build-arg BYTEHIDE_TOKEN=bh_xxxxxxxxxxxx -t myapp .Or in CI/CD, inject from a secret:
docker build --build-arg BYTEHIDE_TOKEN=${{ secrets.BYTEHIDE_TOKEN }} -t myapp .docker build --build-arg BYTEHIDE_TOKEN=${{ secrets.BYTEHIDE_TOKEN }} -t myapp .Verifying the Agent in Docker
After building and running the container:
# Check if the agent files are in the image
docker run --rm myapp ls /opt/bytehide/agent/
# Check if environment variables are set
docker run --rm myapp printenv | grep -E "DOTNET_STARTUP|BYTEHIDE|ASPNETCORE_HOSTING"
# Run the app and check for the agent init message
docker run --rm -e BYTEHIDE_DEBUG=true myapp
# Look for: [ByteHide Server Agent] Initialized (PID: xxxxx)# Check if the agent files are in the image
docker run --rm myapp ls /opt/bytehide/agent/
# Check if environment variables are set
docker run --rm myapp printenv | grep -E "DOTNET_STARTUP|BYTEHIDE|ASPNETCORE_HOSTING"
# Run the app and check for the agent init message
docker run --rm -e BYTEHIDE_DEBUG=true myapp
# Look for: [ByteHide Server Agent] Initialized (PID: xxxxx)Platform Summary
| Container OS | Install Method | Env Vars |
|---|---|---|
| Linux (Debian/Ubuntu) | curl | bash install.sh | source /etc/profile.d/bytehide-agent.sh in entrypoint |
| Linux (Alpine) | curl | bash install.sh (auto-detects musl) | source /etc/profile.d/bytehide-agent.sh in entrypoint |
| Windows Server Core | PowerShell install.ps1 | ENV in Dockerfile |
| Windows Nano Server | dotnet tool install + multi-stage copy | ENV in Dockerfile |
Troubleshooting
Agent not loading in container
Check the entrypoint sources the env vars:
Bashdocker run --rm myapp printenv DOTNET_STARTUP_HOOKSdocker run --rm myapp printenv DOTNET_STARTUP_HOOKSIf empty, the entrypoint isn't loading them.
For Linux containers, make sure the entrypoint uses bash:
DOCKERFILE# Wrong - doesn't source profile ENTRYPOINT ["dotnet", "myapp.dll"] # Correct - sources profile first ENTRYPOINT ["/bin/bash", "-c", "source /etc/profile.d/bytehide-agent.sh && exec dotnet myapp.dll"]# Wrong - doesn't source profile ENTRYPOINT ["dotnet", "myapp.dll"] # Correct - sources profile first ENTRYPOINT ["/bin/bash", "-c", "source /etc/profile.d/bytehide-agent.sh && exec dotnet myapp.dll"]For Windows containers,
ENVin Dockerfile is the most reliable approach.
curl not found
Some minimal images don't include curl. Install it first: apt-get install -y curl ca-certificates (Debian/Ubuntu) or apk add --no-cache curl bash (Alpine).
Permission denied during install
The agent installs to /opt/bytehide/agent/ which requires root. Docker RUN commands run as root by default. If you're using a non-root user:
USER root
RUN curl -sSL ... | bash -s -- --token <token>
USER appuserUSER root
RUN curl -sSL ... | bash -s -- --token <token>
USER appuserNext Steps
- Agent CLI Reference - Manage the agent (status, config, logs, uninstall)
- JSON Configuration - Customize protection rules
- Windows Installation - Install on Windows Server
- Linux & macOS Installation - Install on bare metal