Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/deploy.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ This will start the container in the background and detached.
- `docker exec -it safe-settings /bin/sh`
- You will now be inside the running **Docker** container and can perform any troubleshooting needed

### Troubleshooting Docker Build and Runtime Issues
For detailed guidance on debugging Docker image builds, runtime failures, and comparing local vs. GHCR images, see [docker-debugging.md](docker-debugging.md).

## Deploy the app to AWS Lambda

### Production-Ready Template
Expand Down
181 changes: 181 additions & 0 deletions docs/docker-debugging.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@

# Docker Build and Test Debugging Runbook

This document summarizes the Docker experiments done for this repo and converts them into a repeatable workflow for debugging local image builds and GHCR images.

## Goals

- Build and test the app image from local source.
- Compare behavior with the published image from GHCR.
- Quickly diagnose common failures (container startup, shell access, port exposure, env setup).

## What We Learned From The Experiments

- The image is Alpine-based, so use /bin/sh, not /bin/bash.
- Use docker rm (or docker container rm) to remove containers. Commands like docker delete, docker destroy, or docker remove do not exist.
- To pass host binding correctly, use HOST=0.0.0.0 (equal sign), not HOST:0.0.0.0.
- Port mapping is required for host access: -p 3000:3000.
- Supplying .env values is required for realistic startup testing.
- Testing both local and GHCR images with the same runtime flags makes behavior comparisons easier.

## Prerequisites

- Docker is installed and running.
- A valid .env file exists at repo root.
- You are in repo root.

## 1) Build And Test Local Image

Build the local image:

```bash
docker build -t safe-settings:local .
```

Run container in foreground with explicit runtime env and port mapping:

```bash
docker run --name safe-settings-local \
--env-file ./.env \
--env NODE_ENV=development \
--env HOST=0.0.0.0 \
-p 3000:3000 \
-it safe-settings:local
Comment on lines +39 to +43
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The command examples use tab characters for indentation (e.g., the --env-file / --env / -p lines). This repo’s .editorconfig specifies indent_style = space, and tabs often paste inconsistently across shells/editors. Replace the leading tabs with spaces throughout the code blocks to keep formatting consistent and copy/paste-friendly.

Suggested change
--env-file ./.env \
--env NODE_ENV=development \
--env HOST=0.0.0.0 \
-p 3000:3000 \
-it safe-settings:local
--env-file ./.env \
--env NODE_ENV=development \
--env HOST=0.0.0.0 \
-p 3000:3000 \
-it safe-settings:local

Copilot uses AI. Check for mistakes.
```

If startup fails, inspect logs:

```bash
docker logs safe-settings-local
```

Shell into running container for investigation:

```bash
docker exec -it safe-settings-local /bin/sh
```

Clean up:

```bash
docker rm -f safe-settings-local
```

## 2) Pull And Test GHCR Image

Pull published image:

```bash
docker pull ghcr.io/github/safe-settings:2.1.19
```
Comment on lines +68 to +70
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The GHCR image tag is hard-coded to 2.1.19 in multiple commands. Other docs in this repo reference different tags (e.g., deploy.md mentions 2.1.13, awslambda.md mentions 2.1.17), so this is likely to become stale/confusing. Consider using a placeholder (e.g., $SAFE_SETTINGS_TAG) and/or pointing readers to where to find the current recommended tag, then reuse that consistently across docs.

Copilot uses AI. Check for mistakes.

Run with the same env and port flags used for local testing:

```bash
docker run --name safe-settings-ghcr \
--env-file ./.env \
--env NODE_ENV=development \
--env HOST=0.0.0.0 \
-p 3000:3000 \
-it ghcr.io/github/safe-settings:2.1.19
```

Inspect logs:

```bash
docker logs safe-settings-ghcr
```

Debug inside container:

```bash
docker exec -it safe-settings-ghcr /bin/sh
```

Clean up:

```bash
docker rm -f safe-settings-ghcr
```

## 3) Fast Differential Debug (Local vs GHCR)

Use this when one image works and the other does not.

1. Run both images with identical flags (env, HOST, port mapping).
2. Compare startup logs side-by-side.
3. Compare environment inside each container:

```bash
docker exec -it safe-settings-local /bin/sh -c 'env | sort'
docker exec -it safe-settings-ghcr /bin/sh -c 'env | sort'
```

4. Confirm app process is listening on expected port inside container:

```bash
docker exec -it safe-settings-local /bin/sh -c 'netstat -lntp 2>/dev/null || ss -lntp'
docker exec -it safe-settings-ghcr /bin/sh -c 'netstat -lntp 2>/dev/null || ss -lntp'
```

5. Validate host reachability:

```bash
curl -i http://localhost:3000/
```

## 4) Common Failure Patterns And Fixes

Symptom: container exits immediately.
Likely causes:
- Missing required variables in .env.
- Invalid app credentials.
Checks:
- docker logs <container-name>
- Confirm .env has required app settings.

Symptom: cannot connect from host to localhost:3000.
Likely causes:
- Missing -p 3000:3000.
- App not binding to all interfaces.
Checks:
- Ensure HOST=0.0.0.0 is set.
- Ensure port mapping is present.

Symptom: cannot shell into container with bash.
Likely cause:
- Alpine image does not include bash.
Fix:
- Use /bin/sh.

Symptom: name conflict when re-running tests.
Likely cause:
- Old container still exists.
Fix:
- docker rm -f <container-name>

## 5) Minimal Known-Good Commands

Local:

```bash
docker build -t safe-settings:local . && \
docker run --rm --name safe-settings-local \
--env-file ./.env \
--env NODE_ENV=development \
--env HOST=0.0.0.0 \
-p 3000:3000 \
-it safe-settings:local
```

GHCR:

```bash
docker pull ghcr.io/github/safe-settings:2.1.19 && \
docker run --rm --name safe-settings-ghcr \
--env-file ./.env \
--env NODE_ENV=development \
--env HOST=0.0.0.0 \
-p 3000:3000 \
-it ghcr.io/github/safe-settings:2.1.19
```
Loading