mirror of
https://github.com/casjaysdevdocker/claude
synced 2026-06-23 20:01:01 -04:00
🗃️ Removed the .claude/settings.local.json 🗃️
Dockerfile .env.scripts .gitattributes .gitea/workflows/docker.yaml .gitignore README.md rootfs/usr/local/bin/entrypoint.sh rootfs/usr/local/bin/pkmgr
This commit is contained in:
+8
-7
@@ -25,11 +25,12 @@ DOCKER_ENTYPOINT_HEALTH_ENDPOINTS="$DOCKER_ENTYPOINT_HEALTH_ENDPOINTS"
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# Dockerfile info
|
||||
ENV_DOCKERFILE="Dockerfile"
|
||||
ENV_IMAGE_NAME="claude"
|
||||
# ENV_REGISTRY_REPO: Registry repository/image name
|
||||
ENV_REGISTRY_REPO="claude"
|
||||
ENV_USE_TEMPLATE="alpine"
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# Maintainer info
|
||||
ENV_ORG_NAME="casjaysdevdocker"
|
||||
ENV_REGISTRY_ORG="casjaysdevdocker"
|
||||
ENV_VENDOR="CasjaysDev"
|
||||
ENV_AUTHOR="CasjaysDev"
|
||||
ENV_MAINTAINER="CasjaysDev <docker-admin@casjaysdev.pro>"
|
||||
@@ -37,12 +38,12 @@ ENV_MAINTAINER="CasjaysDev <docker-admin@casjaysdev.pro>"
|
||||
# Repository URLs (Full URLs)
|
||||
# ENV_GIT_REPO_URL: Complete Git repository URL for source code
|
||||
ENV_GIT_REPO_URL="https://github.com/casjaysdevdocker/claude"
|
||||
# ENV_REGISTRY_URL: Complete registry URL for reference (NOT used for pushing)
|
||||
ENV_REGISTRY_URL="https://hub.docker.com/casjaysdevdocker/claude"
|
||||
# ENV_REGISTRY_URL: Registry provider base URL (for example https://docker.io)
|
||||
ENV_REGISTRY_URL="https://docker.io"
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# Push Configuration
|
||||
# ENV_IMAGE_PUSH: Complete push destination (this IS used for pushing)
|
||||
ENV_IMAGE_PUSH="casjaysdevdocker/claude"
|
||||
# ENV_REGISTRY_PUSH: Complete push destination derived from registry/org/repo
|
||||
ENV_REGISTRY_PUSH="casjaysdevdocker/claude"
|
||||
# ENV_IMAGE_TAG: Default tag for the image
|
||||
ENV_IMAGE_TAG="latest"
|
||||
# ENV_ADD_TAGS: Additional tags, comma-separated (USE_DATE = auto date tag)
|
||||
@@ -57,7 +58,7 @@ ENV_PULL_URL="casjaysdev/alpine"
|
||||
# ENV_DISTRO_TAG: Tag for the pull source image
|
||||
ENV_DISTRO_TAG="${IMAGE_VERSION}"
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# Env - No ports needed for CLI application
|
||||
# Env
|
||||
SERVICE_PORT=""
|
||||
EXPOSE_PORTS=""
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
# Template generated on Tue Jan 13 10:43:03 AM EST 2026 from https://github.com/alexkaratarakis/gitattributes"
|
||||
# Template generated on Sat Nov 29 11:57:12 AM EST 2025 from https://github.com/alexkaratarakis/gitattributes"
|
||||
# Common settings that generally should always be used with your language specific settings
|
||||
# Auto detect text files and perform LF normalization
|
||||
* text=auto
|
||||
|
||||
@@ -19,13 +19,20 @@ jobs:
|
||||
- name: Get Meta
|
||||
id: meta
|
||||
run: |
|
||||
echo DATE_TAG=$(date +'%y%m') >> $GITHUB_OUTPUT
|
||||
echo REPO_VERSION=$(git describe --tags --always | sed 's/^v//') >> $GITHUB_OUTPUT
|
||||
echo DOCKER_ORG=$(echo ${GITHUB_REPOSITORY} | awk -F"/" '{print $1}') >> $GITHUB_OUTPUT
|
||||
echo DOCKER_TAG=$([ -n "$DOCKER_TAG" ] && echo ${DOCKER_TAG} || echo "latest") >> $GITHUB_OUTPUT
|
||||
echo DOCKER_HUB=$([ -n "$DOCKER_HUB" ] && echo ${DOCKER_HUB} || echo "docker.io") >> $GITHUB_OUTPUT
|
||||
echo REPO_NAME=$(echo ${GITHUB_REPOSITORY} | awk -F"/" '{print $2}' | sed 's|^docker-||g') >> $GITHUB_OUTPUT
|
||||
echo "$DOCKER_HUB/$DOCKER_ORG/$REPO_NAME:$DOCKER_TAG"
|
||||
repo_version="$(git describe --tags --always)"
|
||||
repo_version="${repo_version#v}"
|
||||
docker_org="${GITHUB_REPOSITORY%%/*}"
|
||||
repo_name="${GITHUB_REPOSITORY#*/}"
|
||||
repo_name="${repo_name#docker-}"
|
||||
docker_tag="${DOCKER_TAG:-latest}"
|
||||
docker_hub="${DOCKER_HUB:-docker.io}"
|
||||
printf 'DATE_TAG=%s\n' "$(date +'%y%m')" >> "$GITHUB_OUTPUT"
|
||||
printf 'REPO_VERSION=%s\n' "$repo_version" >> "$GITHUB_OUTPUT"
|
||||
printf 'DOCKER_ORG=%s\n' "$docker_org" >> "$GITHUB_OUTPUT"
|
||||
printf 'DOCKER_TAG=%s\n' "$docker_tag" >> "$GITHUB_OUTPUT"
|
||||
printf 'DOCKER_HUB=%s\n' "$docker_hub" >> "$GITHUB_OUTPUT"
|
||||
printf 'REPO_NAME=%s\n' "$repo_name" >> "$GITHUB_OUTPUT"
|
||||
printf '%s\n' "$docker_hub/$docker_org/$repo_name:$docker_tag"
|
||||
|
||||
- name: Set up Docker BuildX
|
||||
uses: docker/setup-buildx-action@v2
|
||||
@@ -58,3 +65,4 @@ jobs:
|
||||
tags: |
|
||||
${{ steps.meta.outputs.DOCKER_HUB }}/${{ steps.meta.outputs.DOCKER_ORG }}/${{ steps.meta.outputs.REPO_NAME }}:${{ steps.meta.outputs.DATE_TAG }}
|
||||
${{ steps.meta.outputs.DOCKER_HUB }}/${{ steps.meta.outputs.DOCKER_ORG }}/${{ steps.meta.outputs.REPO_NAME }}:${{ steps.meta.outputs.DOCKER_TAG }}
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
# gitignore created on 01/22/26 at 10:43
|
||||
# gitignore created on 05/05/26 at 14:38
|
||||
# Disable reminder in prompt
|
||||
ignoredirmessage
|
||||
|
||||
|
||||
+22
-16
@@ -76,7 +76,13 @@ RUN set -e; \
|
||||
|
||||
RUN set -e; \
|
||||
echo "Setting up prerequisites"; \
|
||||
true
|
||||
apk --no-cache add bash; \
|
||||
SH_CMD="$(which sh 2>/dev/null||command -v sh 2>/dev/null)"; \
|
||||
BASH_CMD="$(which bash 2>/dev/null||command -v bash 2>/dev/null)"; \
|
||||
[ -x "$BASH_CMD" ] && symlink "$BASH_CMD" "/bin/sh" || true; \
|
||||
[ -x "$BASH_CMD" ] && symlink "$BASH_CMD" "/usr/bin/sh" || true; \
|
||||
[ -x "$BASH_CMD" ] && [ "$SH_CMD" != "/bin/sh" ] && symlink "$BASH_CMD" "$SH_CMD" || true; \
|
||||
[ -n "$BASH_CMD" ] && sed -i 's|root:x:.*|root:x:0:0:root:/root:'$BASH_CMD'|g' "/etc/passwd" || true
|
||||
|
||||
ENV SHELL="/bin/bash"
|
||||
SHELL [ "/bin/bash", "-c" ]
|
||||
@@ -91,7 +97,12 @@ RUN echo "Initializing the system"; \
|
||||
|
||||
RUN echo "Creating and editing system files "; \
|
||||
$SHELL_OPTS; \
|
||||
[ -f "/root/.profile" ] || touch "/root/.profile"; \
|
||||
rm -Rf "/etc/apk/repositories"; \
|
||||
[ "$DISTRO_VERSION" = "latest" ] && DISTRO_VERSION="edge";[ "$DISTRO_VERSION" = "edge" ] || DISTRO_VERSION="v${DISTRO_VERSION}"; \
|
||||
echo "http://dl-cdn.alpinelinux.org/alpine/${DISTRO_VERSION}/main" >>"/etc/apk/repositories"; \
|
||||
echo "http://dl-cdn.alpinelinux.org/alpine/${DISTRO_VERSION}/community" >>"/etc/apk/repositories"; \
|
||||
if [ "${DISTRO_VERSION}" = "edge" ]; then echo "http://dl-cdn.alpinelinux.org/alpine/${DISTRO_VERSION}/testing" >>"/etc/apk/repositories";fi; \
|
||||
apk update; apk upgrade --no-cache; \
|
||||
if [ -f "/root/docker/setup/01-system.sh" ];then echo "Running the system script";/root/docker/setup/01-system.sh||{ echo "Failed to execute /root/docker/setup/01-system.sh" >&2 && exit 10; };echo "Done running the system script";fi; \
|
||||
echo ""
|
||||
|
||||
@@ -118,7 +129,7 @@ RUN echo "Updating system files "; \
|
||||
echo 'hosts: files dns' >"/etc/nsswitch.conf"; \
|
||||
[ "$PHP_VERSION" = "system" ] && PHP_VERSION="php" || true; \
|
||||
PHP_BIN="$(command -v ${PHP_VERSION} 2>/dev/null || true)"; \
|
||||
PHP_FPM="$(ls /usr/*bin/php*fpm* 2>/dev/null || true)"; \
|
||||
set -- /usr/*bin/php*fpm*; [ -e "$1" ] && PHP_FPM="$1" || PHP_FPM=""; \
|
||||
pip_bin="$(command -v python3 2>/dev/null || command -v python2 2>/dev/null || command -v python 2>/dev/null || true)"; \
|
||||
py_version="$(command $pip_bin --version | sed 's|[pP]ython ||g' | awk -F '.' '{print $1$2}' | grep '[0-9]' || true)"; \
|
||||
[ "$py_version" -gt "310" ] && pip_opts="--break-system-packages " || pip_opts=""; \
|
||||
@@ -135,7 +146,7 @@ RUN echo "Updating system files "; \
|
||||
|
||||
RUN echo "Custom Settings"; \
|
||||
$SHELL_OPTS; \
|
||||
echo ""
|
||||
echo ""
|
||||
|
||||
RUN echo "Setting up users and scripts "; \
|
||||
$SHELL_OPTS; \
|
||||
@@ -152,12 +163,7 @@ RUN echo "Setting OS Settings "; \
|
||||
|
||||
RUN echo "Custom Applications"; \
|
||||
$SHELL_OPTS; \
|
||||
echo "Installing Claude Code CLI via native installer"; \
|
||||
curl -fsSL https://claude.ai/install.sh | bash || { echo "Failed to install Claude Code CLI" >&2 && exit 10; }; \
|
||||
echo "Configuring Docker"; \
|
||||
mkdir -p /etc/docker; \
|
||||
echo '{"storage-driver":"vfs"}' > /etc/docker/daemon.json; \
|
||||
echo ""
|
||||
echo ""
|
||||
|
||||
RUN echo "Running custom commands"; \
|
||||
if [ -f "/root/docker/setup/05-custom.sh" ];then echo "Running the custom script";/root/docker/setup/05-custom.sh||{ echo "Failed to execute /root/docker/setup/05-custom.sh" && exit 10; };echo "Done running the custom script";fi; \
|
||||
@@ -180,7 +186,7 @@ RUN echo "Deleting unneeded files"; \
|
||||
rm -rf /lib/systemd/system/sockets.target.wants/*udev* || true; \
|
||||
rm -rf /lib/systemd/system/sockets.target.wants/*initctl* || true; \
|
||||
rm -Rf /usr/share/doc/* /var/tmp/* /var/cache/*/* /root/.cache/* /usr/share/info/* /tmp/* || true; \
|
||||
if [ -d "/lib/systemd/system/sysinit.target.wants" ];then cd "/lib/systemd/system/sysinit.target.wants" && rm -f $(ls | grep -v systemd-tmpfiles-setup);fi; \
|
||||
if [ -d "/lib/systemd/system/sysinit.target.wants" ];then cd "/lib/systemd/system/sysinit.target.wants" && for want_file in *; do [ "$want_file" = "systemd-tmpfiles-setup" ] || rm -f "$want_file"; done; fi; \
|
||||
if [ -f "/root/docker/setup/07-cleanup.sh" ];then echo "Running the cleanup script";/root/docker/setup/07-cleanup.sh||{ echo "Failed to execute /root/docker/setup/07-cleanup.sh" >&2 && exit 10; };echo "Done running the cleanup script";fi; \
|
||||
echo ""
|
||||
|
||||
@@ -224,8 +230,8 @@ LABEL org.opencontainers.image.authors="${LICENSE}"
|
||||
LABEL org.opencontainers.image.created="${BUILD_DATE}"
|
||||
LABEL org.opencontainers.image.version="${BUILD_VERSION}"
|
||||
LABEL org.opencontainers.image.schema-version="${BUILD_VERSION}"
|
||||
LABEL org.opencontainers.image.url="https://hub.docker.com/casjaysdevdocker/claude"
|
||||
LABEL org.opencontainers.image.source="https://hub.docker.com/casjaysdevdocker/claude"
|
||||
LABEL org.opencontainers.image.url="https://docker.io/casjaysdevdocker/claude"
|
||||
LABEL org.opencontainers.image.source="https://docker.io/casjaysdevdocker/claude"
|
||||
LABEL org.opencontainers.image.vcs-type="Git"
|
||||
LABEL org.opencontainers.image.revision="${GIT_COMMIT}"
|
||||
LABEL org.opencontainers.image.source="https://github.com/casjaysdevdocker/claude"
|
||||
@@ -234,7 +240,7 @@ LABEL com.github.containers.toolbox="false"
|
||||
|
||||
ENV ENV=~/.bashrc
|
||||
ENV USER="${USER}"
|
||||
ENV PATH="/usr/local/bin:/root/.local/bin:${PATH}"
|
||||
ENV PATH="${PATH}"
|
||||
ENV TZ="${TIMEZONE}"
|
||||
ENV SHELL="/bin/bash"
|
||||
ENV TIMEZONE="${TZ}"
|
||||
@@ -250,11 +256,10 @@ ENV NODE_MANAGER="${NODE_MANAGER}"
|
||||
ENV PHP_VERSION="${PHP_VERSION}"
|
||||
ENV DISTRO_VERSION="${IMAGE_VERSION}"
|
||||
ENV WWW_ROOT_DIR="${WWW_ROOT_DIR}"
|
||||
ENV USE_BUILTIN_RIPGREP="0"
|
||||
|
||||
COPY --from=build /. /
|
||||
|
||||
VOLUME [ "/config","/app","/data" ]
|
||||
VOLUME [ "/config","/data" ]
|
||||
|
||||
EXPOSE ${SERVICE_PORT} ${ENV_PORTS}
|
||||
|
||||
@@ -262,3 +267,4 @@ STOPSIGNAL SIGRTMIN+3
|
||||
|
||||
ENTRYPOINT [ "tini", "-p", "SIGTERM","--", "/usr/local/bin/entrypoint.sh" ]
|
||||
HEALTHCHECK --start-period=10m --interval=5m --timeout=15s CMD [ "/usr/local/bin/entrypoint.sh", "healthcheck" ]
|
||||
|
||||
|
||||
@@ -1,18 +1,6 @@
|
||||
## 👋 Welcome to claude 🚀
|
||||
|
||||
Docker container for running Claude Code CLI with **full Docker-in-Docker support**.
|
||||
|
||||
This container provides a complete development environment with:
|
||||
|
||||
- **Persistent screen sessions** - Detach/reattach to Claude without losing context
|
||||
- **Full Docker-in-Docker (DinD)** - Run Docker commands inside Claude Code
|
||||
- **Claude Code CLI** with `--dangerously-skip-permissions` pre-configured
|
||||
- **Persistent configuration** in `/config` - Settings and authentication
|
||||
- **Persistent data** in `/data` - Logs, databases, caches (like `/var`)
|
||||
- **Persistent workspace** in `/app` - Your project code
|
||||
- **Multiple authentication methods** - Claude Pro subscription or API key
|
||||
- **Pre-installed tools** - Docker, Docker Compose, containerd, git, curl, bash, screen
|
||||
- **Native Claude Code installer** - Uses official installer (not deprecated npm package)
|
||||
claude README
|
||||
|
||||
|
||||
## Install my system scripts
|
||||
@@ -30,379 +18,42 @@ dockermgr update claude
|
||||
|
||||
## Install and run container
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Docker installed with `--privileged` support
|
||||
- Authentication via one of:
|
||||
- **Claude Pro subscription** (recommended for Max users)
|
||||
- **Anthropic API key** (pay-as-you-go)
|
||||
|
||||
### Authentication Options
|
||||
|
||||
Claude Code supports multiple authentication methods:
|
||||
|
||||
#### Option 1: Claude Pro Subscription (Recommended)
|
||||
|
||||
If you have a Claude Pro subscription with Claude.com:
|
||||
|
||||
- Claude Code will prompt you to authenticate interactively
|
||||
- Supports Pro and Max tier subscriptions
|
||||
- No additional API costs
|
||||
- Just run the container and follow the prompts
|
||||
- **Tip:** Mount `~/.claude` directory to preserve authentication across container restarts
|
||||
|
||||
#### Option 2: Anthropic API Key
|
||||
|
||||
For API-based usage with pay-as-you-go billing:
|
||||
|
||||
1. Go to [console.anthropic.com](https://console.anthropic.com)
|
||||
2. Create an API key
|
||||
3. Pass it via environment: `-e ANTHROPIC_API_KEY=sk-ant-api03-...`
|
||||
|
||||
**Note:** API keys and Claude Pro subscriptions are separate authentication methods. Use whichever fits your use case.
|
||||
|
||||
### Quick Start
|
||||
|
||||
**With Claude Pro Subscription:**
|
||||
|
||||
```shell
|
||||
# Start container with Claude in persistent screen session
|
||||
dockerHome="/var/lib/srv/$USER/docker/casjaysdevdocker/claude/claude/latest/rootfs"
|
||||
mkdir -p "/var/lib/srv/$USER/docker/claude/rootfs"
|
||||
git clone "https://github.com/dockermgr/claude" "$HOME/.local/share/CasjaysDev/dockermgr/claude"
|
||||
cp -Rfva "$HOME/.local/share/CasjaysDev/dockermgr/claude/rootfs/." "$dockerHome/"
|
||||
docker run -d \
|
||||
--restart always \
|
||||
--privileged \
|
||||
--restart unless-stopped \
|
||||
--name claude-code \
|
||||
--name casjaysdevdocker-claude-latest \
|
||||
--hostname claude \
|
||||
-e TZ=${TIMEZONE:-America/New_York} \
|
||||
-e PUID=$(id -u) \
|
||||
-e PGID=$(id -g) \
|
||||
-v "$PWD:$PWD:z" \
|
||||
-v "$HOME/.config/claude:/config:z" \
|
||||
-v "$HOME/.local/share/claude:/data:z" \
|
||||
-v "$HOME/.claude:/root/.claude:z" \
|
||||
casjaysdevdocker/claude:latest
|
||||
|
||||
# Attach to Claude (automatically manages screen session)
|
||||
docker exec -it claude-code claude
|
||||
|
||||
# Detach anytime with: Ctrl+A then D
|
||||
# Reattach anytime with: docker exec -it claude-code claude
|
||||
```
|
||||
|
||||
**With API Key:**
|
||||
|
||||
```shell
|
||||
export ANTHROPIC_API_KEY="sk-ant-api03-your-key-here"
|
||||
|
||||
# Start container with Claude in persistent screen session
|
||||
docker run -d \
|
||||
--privileged \
|
||||
--restart unless-stopped \
|
||||
--name claude-code \
|
||||
--hostname claude \
|
||||
-e TZ=${TIMEZONE:-America/New_York} \
|
||||
-e PUID=$(id -u) \
|
||||
-e PGID=$(id -g) \
|
||||
-e ANTHROPIC_API_KEY="$ANTHROPIC_API_KEY" \
|
||||
-v "$PWD:$PWD:z" \
|
||||
-v "$HOME/.config/claude:/config:z" \
|
||||
-v "$HOME/.local/share/claude:/data:z" \
|
||||
-v "$HOME/.claude:/root/.claude:z" \
|
||||
casjaysdevdocker/claude:latest
|
||||
|
||||
# Attach to Claude (automatically manages screen session)
|
||||
docker exec -it claude-code claude
|
||||
|
||||
# Detach anytime with: Ctrl+A then D
|
||||
# Reattach anytime with: docker exec -it claude-code claude
|
||||
```
|
||||
|
||||
**Important notes:**
|
||||
|
||||
**File Permissions (PUID/PGID):**
|
||||
|
||||
- `-e PUID=$(id -u)` and `-e PGID=$(id -g)` set the user ID and group ID for file ownership
|
||||
- When PUID/PGID are set (non-zero), the container creates a `claude` user with your UID/GID
|
||||
- Files created in mounted directories (`/config`, `/data`, `$PWD`) will have **your ownership**, not root
|
||||
- The container process runs as root, but files get your ownership through user mapping
|
||||
- This prevents permission issues when editing files on the host
|
||||
- **Optional:** Omit these (or set to 0) to run as root and have root-owned files
|
||||
|
||||
**Working Directory:**
|
||||
|
||||
- `-v "$PWD:$PWD:z"` mounts current directory to the **same path** inside container
|
||||
- Paths in Claude's context **match your host** exactly
|
||||
- No confusion about `/app` vs actual project location
|
||||
|
||||
**Credentials Mount:**
|
||||
|
||||
- `-v "$HOME/.claude:/root/.claude:z"` is optional but recommended
|
||||
- **Mounts entire `.claude` directory**, not just the credentials file
|
||||
- Avoids Docker creating directory when file doesn't exist
|
||||
- Shares all Claude settings, not just authentication
|
||||
- **Preserves authentication** across container recreations
|
||||
- **Shares credentials** between native Claude Code and containerized version
|
||||
- Only needed for Claude Pro subscription (not needed for API key)
|
||||
|
||||
### One-line attach command
|
||||
|
||||
```shell
|
||||
# Start if not running, then attach to Claude
|
||||
docker start claude-code 2>/dev/null || true && docker exec -it claude-code claude
|
||||
```
|
||||
|
||||
### Pass additional arguments
|
||||
|
||||
```shell
|
||||
# Pass custom arguments to Claude Code CLI
|
||||
docker run -it --rm \
|
||||
--privileged \
|
||||
-e CLAUDE_ADDITIONAL_ARGS="--model opus-4" \
|
||||
-v "$PWD:$PWD:z" \
|
||||
-v "$HOME/.config/claude:/config:z" \
|
||||
-v "$HOME/.local/share/claude:/data:z" \
|
||||
-v "$dockerHome/data:/data:z" \
|
||||
-v "$dockerHome/config:/config:z" \
|
||||
-p 80:80 \
|
||||
casjaysdevdocker/claude:latest
|
||||
```
|
||||
|
||||
## Persistent Sessions with Screen
|
||||
|
||||
Claude Code runs inside a **persistent `screen` session** by default. This allows you to:
|
||||
|
||||
- **Detach** from Claude without stopping it
|
||||
- **Reattach** to your existing session anytime
|
||||
- Keep your conversation history and context
|
||||
- Run long tasks in the background
|
||||
|
||||
### Screen Session Management
|
||||
|
||||
Claude automatically runs in a persistent screen session. Simply run:
|
||||
|
||||
```bash
|
||||
docker exec -it claude-code claude
|
||||
```
|
||||
|
||||
This will:
|
||||
|
||||
- **Attach** to existing session if one exists
|
||||
- **Create** a new session if none exists
|
||||
|
||||
No need to remember screen commands!
|
||||
|
||||
### Usage Examples
|
||||
|
||||
**Typical Workflow:**
|
||||
|
||||
```bash
|
||||
# 1. Start container (first time only)
|
||||
docker run -d --privileged --name claude-code \
|
||||
-e PUID=$(id -u) -e PGID=$(id -g) \
|
||||
-v "$PWD:$PWD:z" \
|
||||
-v "$HOME/.config/claude:/config:z" \
|
||||
-v "$HOME/.local/share/claude:/data:z" \
|
||||
casjaysdevdocker/claude:latest
|
||||
|
||||
# 2. Attach to Claude (anytime)
|
||||
docker exec -it claude-code claude
|
||||
|
||||
# 3. Work with Claude...
|
||||
|
||||
# 4. Detach (keeps running): Ctrl+A then D
|
||||
|
||||
# 5. Later, reattach
|
||||
docker exec -it claude-code claude
|
||||
```
|
||||
|
||||
**Fast attach/detach:**
|
||||
|
||||
1. While in Claude, press: `Ctrl+A` then `D` to detach
|
||||
2. Claude continues running in the background
|
||||
3. Run `docker exec -it claude-code claude` to reattach anytime
|
||||
|
||||
### Screen Quick Reference
|
||||
|
||||
| Action | Command |
|
||||
| ---------------------------- | --------------------------------------------------------------------- |
|
||||
| Attach to Claude | `docker exec -it claude-code claude` |
|
||||
| Detach from session | `Ctrl+A` then `D` |
|
||||
| List all sessions | `docker exec -it claude-code screen -ls` |
|
||||
| Kill and restart session | `docker exec -it claude-code screen -X -S claude quit` |
|
||||
| Create new window in session | `Ctrl+A` then `C` |
|
||||
| Switch between windows | `Ctrl+A` then `N` (next) or `P` (previous) |
|
||||
| Scroll in session | `Ctrl+A` then `Esc`, then arrow keys, press `Esc` to exit scroll mode |
|
||||
|
||||
## Full Docker-in-Docker Support
|
||||
|
||||
This container comes with **full Docker-in-Docker (DinD)** enabled by default:
|
||||
|
||||
- Complete Docker daemon runs inside the container
|
||||
- Docker CLI, Docker Compose, and containerd included
|
||||
- Requires `--privileged` flag
|
||||
- Isolated Docker environment from host
|
||||
- Can build images, run containers, use docker-compose
|
||||
|
||||
**Claude Code can execute Docker commands:**
|
||||
|
||||
```bash
|
||||
docker ps
|
||||
docker build -t myapp .
|
||||
docker-compose up -d
|
||||
docker run --rm alpine echo "Hello from nested container"
|
||||
```
|
||||
|
||||
**Note:** Always use `--privileged` flag for full Docker support.
|
||||
|
||||
## via docker-compose
|
||||
|
||||
**With Claude Pro Subscription:**
|
||||
|
||||
```yaml
|
||||
version: "3.8"
|
||||
version: "2"
|
||||
services:
|
||||
claude-code:
|
||||
image: casjaysdevdocker/claude:latest
|
||||
container_name: claude-code
|
||||
hostname: claude
|
||||
privileged: true
|
||||
stdin_open: true
|
||||
tty: true
|
||||
ProjectName:
|
||||
image: casjaysdevdocker/claude
|
||||
container_name: casjaysdevdocker-claude
|
||||
environment:
|
||||
- TZ=America/New_York
|
||||
- PUID=${UID:-1000}
|
||||
- PGID=${GID:-1000}
|
||||
- CLAUDE_ADDITIONAL_ARGS=
|
||||
- HOSTNAME=claude
|
||||
volumes:
|
||||
- "./:${PWD}:z"
|
||||
- "${HOME}/.config/claude:/config:z"
|
||||
- "${HOME}/.local/share/claude:/data:z"
|
||||
- "${HOME}/.claude:/root/.claude:z"
|
||||
restart: unless-stopped
|
||||
- "/var/lib/srv/$USER/docker/casjaysdevdocker/claude/claude/latest/rootfs/data:/data:z"
|
||||
- "/var/lib/srv/$USER/docker/casjaysdevdocker/claude/claude/latest/rootfs/config:/config:z"
|
||||
ports:
|
||||
- 80:80
|
||||
restart: always
|
||||
```
|
||||
|
||||
**With API Key:**
|
||||
|
||||
```yaml
|
||||
version: "3.8"
|
||||
services:
|
||||
claude-code:
|
||||
image: casjaysdevdocker/claude:latest
|
||||
container_name: claude-code
|
||||
hostname: claude
|
||||
privileged: true
|
||||
stdin_open: true
|
||||
tty: true
|
||||
environment:
|
||||
- TZ=America/New_York
|
||||
- PUID=${UID:-1000}
|
||||
- PGID=${GID:-1000}
|
||||
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
|
||||
- CLAUDE_ADDITIONAL_ARGS=
|
||||
volumes:
|
||||
- "./:${PWD}:z"
|
||||
- "${HOME}/.config/claude:/config:z"
|
||||
- "${HOME}/.local/share/claude:/data:z"
|
||||
- "${HOME}/.claude:/root/.claude:z"
|
||||
restart: unless-stopped
|
||||
```
|
||||
|
||||
Save as `docker-compose.yml` and run:
|
||||
|
||||
```shell
|
||||
# With Claude Pro - no API key needed
|
||||
docker-compose up -d
|
||||
docker-compose exec claude-code claude
|
||||
|
||||
# With API key
|
||||
export ANTHROPIC_API_KEY="sk-ant-api03-..."
|
||||
docker-compose up -d
|
||||
docker-compose exec claude-code claude
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### Environment Variables
|
||||
|
||||
**Authentication:**
|
||||
|
||||
- `ANTHROPIC_API_KEY` (optional): Your Anthropic API key
|
||||
- Not required if using Claude Pro subscription with credentials file
|
||||
- Use either API key OR credentials file, not both
|
||||
|
||||
**User Permissions:**
|
||||
|
||||
- `PUID` (recommended): User ID for file ownership (default: 0/root)
|
||||
- Use `$(id -u)` to match your host user
|
||||
- **Controls file ownership** on mounted volumes (`/config`, `/data`, `$PWD`)
|
||||
- When non-zero, creates a `claude` user inside container with your UID
|
||||
- Container process runs as root, files created get mapped to your UID through `chown`
|
||||
- If set to 0 or omitted, files are owned by root (no user mapping)
|
||||
- `PGID` (recommended): Group ID for file ownership (default: 0/root)
|
||||
- Use `$(id -g)` to match your host group
|
||||
- When non-zero, creates a `claude` group inside container with your GID
|
||||
- Prevents permission issues when editing files on the host
|
||||
- If set to 0 or omitted, files are owned by root group (no group mapping)
|
||||
|
||||
**General:**
|
||||
|
||||
- `TZ` (optional): Timezone (default: America/New_York)
|
||||
- `CLAUDE_ADDITIONAL_ARGS` (optional): Additional arguments to pass to Claude Code CLI
|
||||
- `CLAUDE_CONFIG_DIR` (optional): Config directory path (default: /config/claude)
|
||||
- `CLAUDE_WORK_DIR` (optional): Working directory path (default: current PWD)
|
||||
|
||||
### Settings File
|
||||
|
||||
The container uses a persistent settings file located at `/config/claude/settings.json`.
|
||||
On first run, it will be initialized with a default configuration that includes:
|
||||
|
||||
- Permissions for common operations (Read, Write, WebSearch, Bash commands)
|
||||
- `--dangerously-skip-permissions` flag enabled by default
|
||||
- Pre-configured hooks for file operations
|
||||
- Thinking mode set to "off"
|
||||
- Auto-commit disabled
|
||||
|
||||
You can modify this file to customize Claude Code's behavior. The file persists between container restarts.
|
||||
|
||||
### Volume Mounts
|
||||
|
||||
**Required volumes:**
|
||||
|
||||
- `/config` - Configuration directory (contains settings.json)
|
||||
- `/data` - Application data directory (logs, databases, caches, Docker volumes, etc.)
|
||||
- `$PWD:$PWD` - **Current directory mounted to same path** inside container
|
||||
- Paths in Claude's context match your host exactly
|
||||
- No path translation needed
|
||||
- Files created have your user ownership (when using PUID/PGID)
|
||||
|
||||
**Optional but recommended:**
|
||||
|
||||
- `~/.claude` → `/root/.claude` - Claude Pro authentication and settings
|
||||
- **Preserves authentication** across container recreations
|
||||
- **Shares credentials** with native Claude Code installation (`.credentials.json`)
|
||||
- **Shares all Claude settings** between host and container
|
||||
- **Only needed for Claude Pro** (not required if using API key)
|
||||
- Directory and files created automatically on first authentication
|
||||
- **Better than mounting just the file** - avoids Docker creating directory when file doesn't exist
|
||||
|
||||
**Understanding the directory structure:**
|
||||
|
||||
- `$PWD:$PWD` - Your project source code (transparent path mapping)
|
||||
- `/config` - Container configuration and Claude settings
|
||||
- `/data` - Runtime data (databases, logs, docker volumes, temp files, caches)
|
||||
- Example: `/data/logs` - Application and Docker daemon logs
|
||||
- Example: `/data/postgres` - PostgreSQL data
|
||||
- Example: `/data/mysql` - MySQL data
|
||||
- Example: `/data/redis` - Redis persistence
|
||||
- Similar to `/var` on traditional Linux systems
|
||||
|
||||
### Docker-in-Docker Details
|
||||
|
||||
This container runs a **full Docker daemon** by default:
|
||||
|
||||
- Docker CLI, Docker Compose, containerd pre-installed
|
||||
- Isolated Docker environment (separate from host)
|
||||
- Can build images, run containers, use docker-compose
|
||||
- Requires `--privileged` flag
|
||||
- Uses VFS storage driver for compatibility
|
||||
- Docker daemon starts automatically on container startup
|
||||
|
||||
## Get source files
|
||||
|
||||
```shell
|
||||
@@ -422,94 +73,6 @@ cd "$HOME/Projects/github/casjaysdevdocker/claude"
|
||||
buildx
|
||||
```
|
||||
|
||||
## Quick Reference
|
||||
|
||||
### Start Container (First Time)
|
||||
|
||||
```bash
|
||||
# Claude Pro users
|
||||
docker run -d --privileged --restart unless-stopped --name claude-code \
|
||||
-e PUID=$(id -u) -e PGID=$(id -g) \
|
||||
-v "$HOME/.config/claude:/config:z" \
|
||||
-v "$HOME/.local/share/claude:/data:z" \
|
||||
-v "$PWD:$PWD:z" \
|
||||
-v "$HOME/.claude:/root/.claude:z" \
|
||||
casjaysdevdocker/claude:latest
|
||||
|
||||
# API Key users
|
||||
export ANTHROPIC_API_KEY="sk-ant-api03-..."
|
||||
docker run -d --privileged --restart unless-stopped --name claude-code \
|
||||
-e PUID=$(id -u) -e PGID=$(id -g) \
|
||||
-e ANTHROPIC_API_KEY="$ANTHROPIC_API_KEY" \
|
||||
-v "$HOME/.config/claude:/config:z" \
|
||||
-v "$HOME/.local/share/claude:/data:z" \
|
||||
-v "$PWD:$PWD:z" \
|
||||
-v "$HOME/.claude:/root/.claude:z" \
|
||||
casjaysdevdocker/claude:latest
|
||||
```
|
||||
|
||||
### Daily Usage
|
||||
|
||||
```bash
|
||||
# Attach to Claude (creates or attaches to screen session)
|
||||
docker exec -it claude-code claude
|
||||
|
||||
# Detach: Ctrl+A then D
|
||||
|
||||
# One-liner to start container and attach
|
||||
docker start claude-code 2>/dev/null || true && docker exec -it claude-code claude
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "Cannot start Docker-in-Docker daemon - insufficient privileges"
|
||||
|
||||
- **Solution:** Add `--privileged` flag to your docker run command
|
||||
- This container requires privileged mode for full Docker-in-Docker support
|
||||
|
||||
### Authentication prompts
|
||||
|
||||
- **Claude Pro users:** Follow the interactive prompts to authenticate
|
||||
- **API users:** Set `ANTHROPIC_API_KEY` environment variable
|
||||
|
||||
### Credentials file issues
|
||||
|
||||
**Problem:** Authentication not persisting across container restarts
|
||||
|
||||
**Solution:** Mount the entire `~/.claude` directory, not just the file:
|
||||
```bash
|
||||
# ✅ Correct - mount directory
|
||||
-v "$HOME/.claude:/root/.claude:z"
|
||||
|
||||
# ❌ Wrong - Docker creates directory if file doesn't exist
|
||||
-v "$HOME/.claude/.credentials.json:/root/.claude/.credentials.json:z"
|
||||
```
|
||||
|
||||
**Why:** If the file doesn't exist on host, Docker creates it as a **directory** instead, breaking authentication.
|
||||
|
||||
### Docker commands not working inside container
|
||||
|
||||
- Ensure you're using `--privileged` flag
|
||||
- Wait a few seconds for Docker daemon to initialize
|
||||
- Check logs: `docker logs claude-code`
|
||||
|
||||
### Screen session issues
|
||||
|
||||
```bash
|
||||
# Just run claude - it will create a session if needed
|
||||
docker exec -it claude-code claude
|
||||
|
||||
# List all screen sessions (advanced)
|
||||
docker exec -it claude-code screen -ls
|
||||
|
||||
# Force kill screen session and create new one
|
||||
docker exec -it claude-code screen -X -S claude quit
|
||||
docker exec -it claude-code claude
|
||||
|
||||
# Manually restart the init script (if needed)
|
||||
docker exec -it claude-code /usr/local/etc/docker/init.d/99-claude.sh
|
||||
```
|
||||
|
||||
## Authors
|
||||
|
||||
🤖 casjay: [Github](https://github.com/casjay) 🤖
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
#!/usr/bin/env bash
|
||||
# shellcheck shell=bash
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
##@Version : 202512161441-git
|
||||
##@Version : 202602061352-git
|
||||
# @@Author : Jason Hempstead
|
||||
# @@Contact : jason@casjaysdev.pro
|
||||
# @@License : WTFPL
|
||||
# @@ReadME : entrypoint.sh --help
|
||||
# @@Copyright : Copyright: (c) 2026 Jason Hempstead, Casjays Developments
|
||||
# @@Created : Thursday, Jan 22, 2026 10:43 EST
|
||||
# @@Created : Tuesday, May 05, 2026 14:38 EDT
|
||||
# @@File : entrypoint.sh
|
||||
# @@Description : Entrypoint file for claude
|
||||
# @@Changelog : New script
|
||||
@@ -21,56 +21,22 @@
|
||||
# shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# run trap command on exit
|
||||
trap '__trap_exit_handler' EXIT
|
||||
trap '__trap_signal_handler' INT TERM PWR
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
__trap_exit_handler() {
|
||||
local retVal=$?
|
||||
if [ "$SERVICE_IS_RUNNING" != "yes" ] && [ -f "$SERVICE_PID_FILE" ]; then
|
||||
rm -Rf "$SERVICE_PID_FILE" 2>/dev/null || true
|
||||
fi
|
||||
exit $retVal
|
||||
}
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
__trap_signal_handler() {
|
||||
local retVal=$?
|
||||
echo "Container received shutdown signal"
|
||||
if [ "$SERVICE_IS_RUNNING" != "yes" ] && [ -f "$SERVICE_PID_FILE" ]; then
|
||||
rm -Rf "$SERVICE_PID_FILE" 2>/dev/null || true
|
||||
fi
|
||||
exit $retVal
|
||||
}
|
||||
trap 'retVal=$?;[ "$SERVICE_IS_RUNNING" != "yes" ] && [ -f "$SERVICE_PID_FILE" ] && rm -Rf "$SERVICE_PID_FILE";exit $retVal' INT TERM PWR
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# setup debugging - https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html
|
||||
if [ -f "/config/.debug" ] && [ -z "$DEBUGGER_OPTIONS" ]; then
|
||||
export DEBUGGER_OPTIONS="$(<"/config/.debug")"
|
||||
else
|
||||
DEBUGGER_OPTIONS="${DEBUGGER_OPTIONS:-}"
|
||||
fi
|
||||
if [ "$DEBUGGER" = "on" ] || [ -f "/config/.debug" ]; then
|
||||
echo "Enabling debugging"
|
||||
set -o pipefail -x$DEBUGGER_OPTIONS
|
||||
export DEBUGGER="on"
|
||||
else
|
||||
set -o pipefail
|
||||
fi
|
||||
[ -f "/config/.debug" ] && [ -z "$DEBUGGER_OPTIONS" ] && export DEBUGGER_OPTIONS="$(<"/config/.debug")" || DEBUGGER_OPTIONS="${DEBUGGER_OPTIONS:-}"
|
||||
{ [ "$DEBUGGER" = "on" ] || [ -f "/config/.debug" ]; } && echo "Enabling debugging" && set -o pipefail -x$DEBUGGER_OPTIONS && export DEBUGGER="on" || set -o pipefail
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
PATH="/usr/local/bin:/usr/local/etc/docker/bin:/root/.local/bin:/usr/bin:/usr/sbin:/bin:/sbin"
|
||||
PATH="/usr/local/etc/docker/bin:/usr/local/bin:/usr/bin:/usr/sbin:/bin:/sbin"
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# Set bash options
|
||||
SCRIPT_FILE="$0"
|
||||
CONTAINER_NAME="claude"
|
||||
SCRIPT_NAME="$(basename -- "$SCRIPT_FILE" 2>/dev/null)"
|
||||
SCRIPT_NAME="${SCRIPT_FILE##*/}"
|
||||
CONTAINER_NAME="${ENV_CONTAINER_NAME:-$CONTAINER_NAME}"
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# remove whitespaces from beginning argument
|
||||
while :; do
|
||||
if [ "$1" = " " ]; then
|
||||
shift 1
|
||||
else
|
||||
break
|
||||
fi
|
||||
done
|
||||
while :; do [ "$1" = " " ] && shift 1 || break; done
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
[ "$1" = "$SCRIPT_FILE" ] && shift 1
|
||||
[ "$1" = "$SCRIPT_NAME" ] && shift 1
|
||||
@@ -110,19 +76,15 @@ unset set_env
|
||||
# normally root
|
||||
RUNAS_USER="root"
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# Set user and group ID from PUID/PGID env variables
|
||||
# PUID/PGID are numeric IDs, not usernames
|
||||
SERVICE_UID="${PUID:-${SERVICE_UID:-0}}"
|
||||
SERVICE_GID="${PGID:-${SERVICE_GID:-0}}"
|
||||
# Set user and group from env
|
||||
SERVICE_USER="${PUID:-$SERVICE_USER}"
|
||||
SERVICE_GROUP="${PGID:-$SERVICE_GROUP}"
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# Set user and group names (only if not running as root)
|
||||
if [ "$SERVICE_UID" != "0" ] && [ "$SERVICE_GID" != "0" ]; then
|
||||
SERVICE_USER="${SERVICE_USER:-claude}"
|
||||
SERVICE_GROUP="${SERVICE_GROUP:-claude}"
|
||||
else
|
||||
SERVICE_USER="root"
|
||||
SERVICE_GROUP="root"
|
||||
fi
|
||||
# Set user and group ID
|
||||
# set the user id
|
||||
SERVICE_UID="${SERVICE_UID:-0}"
|
||||
# set the group id
|
||||
SERVICE_GID="${SERVICE_GID:-0}"
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# User and group in which the service switches to - IE: nginx,apache,mysql,postgres
|
||||
#SERVICE_USER="${SERVICE_USER:-claude}" # execute command as another user
|
||||
@@ -148,18 +110,11 @@ HEALTH_ENDPOINTS=""
|
||||
export PATH RUNAS_USER SERVICE_USER SERVICE_GROUP SERVICE_UID SERVICE_GID WWW_ROOT_DIR DATABASE_DIR
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# Custom variables
|
||||
CLAUDE_CONFIG_DIR="${CLAUDE_CONFIG_DIR:-/config/claude}"
|
||||
CLAUDE_SETTINGS_FILE="${CLAUDE_SETTINGS_FILE:-$CLAUDE_CONFIG_DIR/settings.json}"
|
||||
CLAUDE_WORK_DIR="${CLAUDE_WORK_DIR:-${PWD:-/app}}"
|
||||
CLAUDE_ADDITIONAL_ARGS="${CLAUDE_ADDITIONAL_ARGS:-}"
|
||||
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# show message
|
||||
__run_message() {
|
||||
if [ "$ENTRYPOINT_MESSAGE" = "yes" ]; then
|
||||
echo "Claude Code CLI is ready"
|
||||
echo "Settings: $CLAUDE_SETTINGS_FILE"
|
||||
echo "Working directory: $CLAUDE_WORK_DIR"
|
||||
fi
|
||||
|
||||
return
|
||||
}
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
@@ -215,7 +170,7 @@ export ENTRYPOINT_DATA_INIT_FILE="${ENTRYPOINT_DATA_INIT_FILE:-/data/.docker_has
|
||||
export ENTRYPOINT_CONFIG_INIT_FILE="${ENTRYPOINT_CONFIG_INIT_FILE:-/config/.docker_has_run}"
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
if [ -n "$CONTAINER_WEB_SERVER_WWW_REPO" ]; then
|
||||
www_temp_dir="/tmp/git/$(basename -- "$CONTAINER_WEB_SERVER_WWW_REPO")"
|
||||
www_temp_dir="/tmp/git/${CONTAINER_WEB_SERVER_WWW_REPO##*/}"
|
||||
rm -Rf "${WWW_ROOT_DIR:?}"/* "${www_temp_dir:?}"/* 2>/dev/null || true
|
||||
mkdir -p "$WWW_ROOT_DIR" "$www_temp_dir" 2>/dev/null || true
|
||||
git clone -q "$CONTAINER_WEB_SERVER_WWW_REPO" "$www_temp_dir" 2>/dev/null || true
|
||||
@@ -278,7 +233,6 @@ mkdir -p "/root" 2>/dev/null || true
|
||||
mkdir -p "/var/run" 2>/dev/null || true
|
||||
mkdir -p "/var/tmp" 2>/dev/null || true
|
||||
mkdir -p "/run/cron" 2>/dev/null || true
|
||||
mkdir -p "/app" 2>/dev/null || true
|
||||
mkdir -p "/data/logs" 2>/dev/null || true
|
||||
mkdir -p "/run/init.d" 2>/dev/null || true
|
||||
mkdir -p "/config/enable" 2>/dev/null || true
|
||||
@@ -413,7 +367,7 @@ if [ "$ENTRYPOINT_FIRST_RUN" != "no" ]; then
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# import hosts file into container
|
||||
if [ -f "/usr/local/etc/hosts" ] && [ "$UPDATE_FILE_HOSTS" = "yes" ]; then
|
||||
cat "/usr/local/etc/hosts" 2>/dev/null | grep -vF "$HOSTNAME" >>"/etc/hosts" 2>/dev/null || true
|
||||
grep -vF "$HOSTNAME" "/usr/local/etc/hosts" 2>/dev/null >>"/etc/hosts" 2>/dev/null || true
|
||||
fi
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# import resolv.conf file into container
|
||||
@@ -487,26 +441,30 @@ fi
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# if no pid assume container restart - clean stale files on restart
|
||||
if [ -f "$ENTRYPOINT_PID_FILE" ]; then
|
||||
# Check if the PID in the file is still running
|
||||
entrypoint_pid=$(cat "$ENTRYPOINT_PID_FILE" 2>/dev/null || echo "")
|
||||
if [ -n "$entrypoint_pid" ] && kill -0 "$entrypoint_pid" 2>/dev/null; then
|
||||
# Process is still running, don't restart services
|
||||
START_SERVICES="no"
|
||||
touch "$ENTRYPOINT_PID_FILE"
|
||||
else
|
||||
# PID file exists but process is dead - this is a restart
|
||||
START_SERVICES="yes"
|
||||
# Clean any stale PID files on restart
|
||||
rm -f /run/__start_init_scripts.pid /run/init.d/*.pid /run/*.pid 2>/dev/null || true
|
||||
fi
|
||||
else
|
||||
START_SERVICES=yes
|
||||
# Clean any stale PID files on first run
|
||||
rm -f /run/.start_init_scripts.pid /run/init.d/*.pid /run/*.pid 2>/dev/null || true
|
||||
rm -f /run/__start_init_scripts.pid /run/init.d/*.pid /run/*.pid 2>/dev/null || true
|
||||
fi
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
if [ "$ENTRYPOINT_MESSAGE" = "yes" ]; then
|
||||
__printf_space "40" "The containers ip address is:" "$CONTAINER_IP4_ADDRESS"
|
||||
fi
|
||||
[ "$ENTRYPOINT_MESSAGE" = "yes" ] && __printf_space "40" "The containers ip address is:" "$CONTAINER_IP4_ADDRESS"
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# Show configured listing processes
|
||||
if [ "$ENTRYPOINT_MESSAGE" = "yes" ] && [ -n "$ENV_PORTS" ]; then
|
||||
show_port=""
|
||||
for port in $ENV_PORTS; do
|
||||
if [ -n "$port" ]; then
|
||||
show_port+="$(printf '%s ' "${port// /}") "
|
||||
fi
|
||||
done
|
||||
for port in $ENV_PORTS; do [ -n "$port" ] && show_port+="$(printf '%s ' "${port// /}") "; done
|
||||
__printf_space "40" "The following ports are open:" "$show_port"
|
||||
unset port show_port
|
||||
fi
|
||||
@@ -520,15 +478,6 @@ __create_service_user "$SERVICE_USER" "$SERVICE_GROUP" "${WORK_DIR:-/home/$SERVI
|
||||
# Modify user if needed
|
||||
__set_user_group_id $SERVICE_USER ${SERVICE_UID:-} ${SERVICE_GID:-}
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# Fix permissions on mounted directories for PUID/PGID
|
||||
if [ "$SERVICE_UID" != "0" ] && [ "$SERVICE_GID" != "0" ] && [ "$SERVICE_USER" != "root" ]; then
|
||||
echo "Applying PUID/PGID permissions: $SERVICE_USER:$SERVICE_GROUP ($SERVICE_UID:$SERVICE_GID)"
|
||||
# Define directories that need permission changes
|
||||
APPLICATION_DIRS="/config /data ${CLAUDE_WORK_DIR}"
|
||||
# Fix ownership on mounted directories
|
||||
__fix_permissions "$SERVICE_USER" "$SERVICE_GROUP"
|
||||
fi
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# Show message
|
||||
__run_message
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
@@ -550,6 +499,9 @@ if [ "$START_SERVICES" = "yes" ] || [ -z "$1" ]; then
|
||||
echo "$$" >"$ENTRYPOINT_PID_FILE"
|
||||
__start_init_scripts "/usr/local/etc/docker/init.d"
|
||||
CONTAINER_INIT="${CONTAINER_INIT:-no}"
|
||||
# Services started successfully - enter monitoring mode
|
||||
__no_exit
|
||||
exit $?
|
||||
fi
|
||||
START_SERVICES="no"
|
||||
fi
|
||||
@@ -559,7 +511,7 @@ export START_SERVICES CONTAINER_INIT ENTRYPOINT_PID_FILE
|
||||
case "$1" in
|
||||
init)
|
||||
shift 1
|
||||
echo "Container has been Initialized"
|
||||
__log_info "Container has been initialized"
|
||||
exit 0
|
||||
;;
|
||||
tail)
|
||||
@@ -590,7 +542,7 @@ logs)
|
||||
clean)
|
||||
log_files="$(find "/data/logs" -type f)"
|
||||
for log in "${log_files[@]}"; do
|
||||
echo "clearing $log"
|
||||
__log_info "Clearing log file: $log"
|
||||
printf '' >$log
|
||||
done
|
||||
;;
|
||||
@@ -603,7 +555,7 @@ logs)
|
||||
cron)
|
||||
shift 1
|
||||
__cron "$@" &
|
||||
echo "cron script is running with pid: $!"
|
||||
__log_info "Cron script is running with PID: $!"
|
||||
exit
|
||||
;;
|
||||
# backup data and config dirs
|
||||
@@ -631,7 +583,7 @@ healthcheck)
|
||||
[ "$healthEnabled" = "yes" ] || exit 0
|
||||
if [ -d "/run/healthcheck" ] && [ "$(ls -A "/run/healthcheck" | wc -l)" -ne 0 ]; then
|
||||
for service in /run/healthcheck/*; do
|
||||
name=$(basename -- $service)
|
||||
name="${service##*/}"
|
||||
services+="$name "
|
||||
done
|
||||
fi
|
||||
@@ -719,11 +671,7 @@ start)
|
||||
export PATH="/usr/local/etc/docker/init.d:$PATH"
|
||||
if [ $# -eq 0 ]; then
|
||||
scripts="$(ls -A "/usr/local/etc/docker/init.d")"
|
||||
if [ -n "$scripts" ]; then
|
||||
echo "$scripts"
|
||||
else
|
||||
echo "No scripts found in: /usr/local/etc/docker/init.d"
|
||||
fi
|
||||
[ -n "$scripts" ] && echo "$scripts" || echo "No scripts found in: /usr/local/etc/docker/init.d"
|
||||
exit
|
||||
elif [ "$1" = "all" ]; then
|
||||
shift $#
|
||||
@@ -742,11 +690,7 @@ start)
|
||||
if [ $# -eq 0 ]; then
|
||||
if [ ! -f "$ENTRYPOINT_PID_FILE" ]; then
|
||||
echo "$$" >"$ENTRYPOINT_PID_FILE"
|
||||
if [ "$START_SERVICES" = "no" ] && [ "$CONTAINER_INIT" = "yes" ]; then
|
||||
:
|
||||
else
|
||||
__start_init_scripts "/usr/local/etc/docker/init.d"
|
||||
fi
|
||||
[ "$START_SERVICES" = "no" ] && [ "$CONTAINER_INIT" = "yes" ] || __start_init_scripts "/usr/local/etc/docker/init.d"
|
||||
fi
|
||||
__no_exit
|
||||
else
|
||||
|
||||
@@ -103,7 +103,7 @@ install)
|
||||
[ -n "$1" ] || exit 0
|
||||
[ "$USER_UID" -eq 0 ] || [ "$USER" = "root" ] || pkmgr_install_cmd="sudo $pkmgr_install_cmd"
|
||||
if [ -f "$1" ]; then
|
||||
install_list="$(cat "$1")"
|
||||
install_list="$(tr '\n' ' ' < "$1")"
|
||||
else
|
||||
install_list="$*"
|
||||
fi
|
||||
@@ -140,3 +140,4 @@ clean)
|
||||
esac
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user