# Start services
./scripts/docker-compose.sh start
# View logs
./scripts/docker-compose.sh logs proxy
# Check status
./scripts/docker-compose.sh status
# Test the proxy
./scripts/docker-compose.sh test
# Stop services
./scripts/docker-compose.sh stop# Start the proxy + Chrome services
docker compose up -d
# View logs
docker compose logs -f proxy
# Stop services
docker compose downThe proxy will be available at:
- HTTP:
http://localhost:8080 - Chrome DevTools:
http://localhost:9222(internal)
The docker-compose.sh script provides convenient shortcuts:
./scripts/docker-compose.sh start # Start all services
./scripts/docker-compose.sh stop # Stop all services
./scripts/docker-compose.sh restart # Restart services
./scripts/docker-compose.sh status # Show service status
./scripts/docker-compose.sh logs proxy # View proxy logs
./scripts/docker-compose.sh chrome-logs # View Chrome logs
./scripts/docker-compose.sh test # Test with sample request
./scripts/docker-compose.sh shell # Open shell in proxy container
./scripts/docker-compose.sh build # Rebuild Docker image
./scripts/docker-compose.sh clean # Remove all containers/volumesNote: When using Docker Compose, Chrome is automatically available at http://chrome:9222 internally, so you don't need to start it separately.
Create or edit config.yml in the project root:
transport:
type: "chromedp"
chromedp:
url: "http://chrome:9222"
pool_size: 5
filter:
allowed:
- "^https://api\\.example\\.com"
- "^https://example\\.com/docs"
conversion:
enabled: true
negotiate_only: false
convert_json: false
tls:
enabled: false # Set to true for HTTPSThe container automatically reads /etc/markdowninthemiddle/config.yml (mapped to your local config.yml).
Create a .env file (copy from .env.example):
# Copy template
cp .env.example .env
# Edit as needed
nano .env
# Start with env file
docker compose --env-file .env up -dCertificates are automatically generated on first startup:
Generated self-signed TLS certificates:
/etc/markdowninthemiddle/certs/cert.pem
/etc/markdowninthemiddle/certs/key.pem
To use your own certificates:
# Place your certs in the certs directory
cp /path/to/your/cert.pem certs/
cp /path/to/your/key.pem certs/
# Update config.yml
tls:
enabled: true
cert_file: /etc/markdowninthemiddle/certs/cert.pem
key_file: /etc/markdowninthemiddle/certs/key.pem
auto_cert: false
docker compose restart proxyThe proxy exposes:
| Port | Protocol | Service | Purpose |
|---|---|---|---|
| 8080 | TCP | Proxy | HTTP or HTTPS (depends on TLS setting) |
| 9222 | TCP | Chrome | DevTools Protocol (internal only) |
To change the proxy port, edit docker-compose.yml:
proxy:
ports:
- "3128:8080" # Use port 3128 insteadThen access the proxy at http://localhost:3128
The container uses these volumes:
| Mount | Container Path | Purpose |
|---|---|---|
./config.yml |
/etc/markdowninthemiddle/config.yml |
Configuration (read-only) |
./certs |
/etc/markdowninthemiddle/certs |
TLS certificates |
./output |
/var/log/markdowninthemiddle/output |
Converted Markdown files |
To add more volumes, edit docker-compose.yml:
proxy:
volumes:
- ./custom-templates:/var/lib/markdowninthemiddle/templatesBoth services include health checks:
# Check status
docker compose ps
# View health of proxy
docker inspect markdowninthemiddle-proxy | grep -A 10 '"Health"'View real-time logs:
# All services
docker compose logs -f
# Proxy only
docker compose logs -f proxy
# Chrome only
docker compose logs -f chromeBuild with custom settings:
docker build \
--build-arg GO_VERSION=1.24.7 \
--build-arg ALPINE_VERSION=3.20 \
-t my-mitm:latest .
docker compose up -dRun container interactively:
docker compose run --rm proxy /bin/bashdocker stats markdowninthemiddle-proxy markdowninthemiddle-chromeAdd to docker-compose.yml:
chrome:
volumes:
- chrome-cache:/root/.cache
- chrome-data:/root/.local
volumes:
chrome-cache:
chrome-data:# Check Chrome is healthy
docker compose ps
# Restart Chrome
docker compose restart chrome
# Wait 5 seconds, restart proxy
sleep 5
docker compose restart proxy# Check logs
docker compose logs proxy
# Manual generation
docker compose exec proxy /app/gencert \
-cert /etc/markdowninthemiddle/certs/cert.pem \
-key /etc/markdowninthemiddle/certs/key.pem# Verify config file exists
ls -la config.yml
# Check container's config
docker compose exec proxy cat /etc/markdowninthemiddle/config.yml
# Verify environment variable
docker compose exec proxy printenv MITM_CONFIGThe proxy + Chrome can use 500MB - 1GB. To limit:
proxy:
mem_limit: 512m
memswap_limit: 512m
chrome:
mem_limit: 1gFor production:
- Use your own certificates (not auto-generated)
- Set MITM_LOG_LEVEL=warn
- Enable caching for frequently accessed content
- Use a reverse proxy (nginx, Traefik) in front for load balancing
- Set resource limits on both containers
- Use named volumes instead of bind mounts
- Enable restart policies (already set to
unless-stopped)
Example production compose:
services:
chrome:
image: chromedp/headless-shell:latest
restart: always
mem_limit: 1g
networks:
- mitm
proxy:
build: .
restart: always
mem_limit: 512m
volumes:
- config:/etc/markdowninthemiddle
- certs:/etc/markdowninthemiddle/certs
- output:/var/log/markdowninthemiddle/output
depends_on:
chrome:
condition: service_healthy
networks:
- mitm
environment:
MITM_LOG_LEVEL: "warn"
MITM_TRANSPORT_CHROMEDP_URL: "http://chrome:9222"
volumes:
config:
certs:
output:
networks:
mitm:
driver: bridgeTo push your image:
docker login
docker tag markdowninthemiddle:latest myregistry/markdowninthemiddle:v1.0
docker push myregistry/markdowninthemiddle:v1.0Then pull in production:
proxy:
image: myregistry/markdowninthemiddle:v1.0