From ad74c9c42f9e27a51fad17e4bf33c935ae7385e4 Mon Sep 17 00:00:00 2001 From: casjay Date: Thu, 29 Jan 2026 19:27:26 -0500 Subject: [PATCH] =?UTF-8?q?=20=F0=9F=A6=88=F0=9F=8F=A0=F0=9F=90=9C?= =?UTF-8?q?=E2=9D=97=20Initial=20Commit=20=E2=9D=97=F0=9F=90=9C?= =?UTF-8?q?=F0=9F=A6=88=F0=9F=8F=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .dockerignore | 17 ++ .env.scripts | 82 +++++++ .gitattributes | 86 +++++++ .gitea/workflows/docker.yaml | 60 +++++ .github/workflows/README.md | 130 ++++++++++ .github/workflows/build-windows.yml | 176 ++++++++++++++ .gitignore | 104 ++++++++ Dockerfile | 228 ++++++++++++++++++ LICENSE.md | 13 + README.md | 106 ++++++++ rootfs/ProgramData/Docker/setup/00-init.ps1 | 26 ++ rootfs/ProgramData/Docker/setup/01-system.ps1 | 15 ++ .../ProgramData/Docker/setup/02-packages.ps1 | 15 ++ rootfs/ProgramData/Docker/setup/03-files.ps1 | 15 ++ rootfs/ProgramData/Docker/setup/04-users.ps1 | 15 ++ rootfs/ProgramData/Docker/setup/05-custom.ps1 | 15 ++ rootfs/ProgramData/Docker/setup/06-post.ps1 | 15 ++ .../ProgramData/Docker/setup/07-cleanup.ps1 | 23 ++ rootfs/Windows/System32/entrypoint.ps1 | 101 ++++++++ rootfs/Windows/System32/pkmgr | 155 ++++++++++++ rootfs/Windows/System32/pkmgr.ps1 | 102 ++++++++ 21 files changed, 1499 insertions(+) create mode 100644 .dockerignore create mode 100644 .env.scripts create mode 100644 .gitattributes create mode 100644 .gitea/workflows/docker.yaml create mode 100644 .github/workflows/README.md create mode 100644 .github/workflows/build-windows.yml create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 LICENSE.md create mode 100644 README.md create mode 100644 rootfs/ProgramData/Docker/setup/00-init.ps1 create mode 100644 rootfs/ProgramData/Docker/setup/01-system.ps1 create mode 100644 rootfs/ProgramData/Docker/setup/02-packages.ps1 create mode 100644 rootfs/ProgramData/Docker/setup/03-files.ps1 create mode 100644 rootfs/ProgramData/Docker/setup/04-users.ps1 create mode 100644 rootfs/ProgramData/Docker/setup/05-custom.ps1 create mode 100644 rootfs/ProgramData/Docker/setup/06-post.ps1 create mode 100644 rootfs/ProgramData/Docker/setup/07-cleanup.ps1 create mode 100644 rootfs/Windows/System32/entrypoint.ps1 create mode 100755 rootfs/Windows/System32/pkmgr create mode 100644 rootfs/Windows/System32/pkmgr.ps1 diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..71c00b7 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,17 @@ +# Files to ignore +# Tell docker to ignore .gitkeep +.gitkeep +# Tell docker to ignore .gitignore +.gitignore +# Tell docker to ignore node_modules/** +node_modules/** +# Tell docker to ignore .node_modules/** +.node_modules/** +# Tell docker to ignore **/.gitkeep +**/.gitkeep +# Tell docker to ignore **/.gitignore +**/.gitignore +# Tell docker to ignore **/node_modules/** +**/node_modules/** +# Tell docker to ignore **/.node_modules/** +**/.node_modules/** diff --git a/.env.scripts b/.env.scripts new file mode 100644 index 0000000..5b1732f --- /dev/null +++ b/.env.scripts @@ -0,0 +1,82 @@ +# - - - - - - - - - - - - - - - - - - - - - - - - - +##@Version : 202601231310-git +# @@Author : CasjaysDev +# @@Contact : CasjaysDev +# @@License : MIT +# @@Copyright : Copyright 2026 CasjaysDev +# @@Created : Fri Jan 23 01:10:09 PM EST 2026 +# @@File : .env.scripts +# @@Description : Variables for gen-dockerfile and buildx scripts +# @@Changelog : newScript +# @@TODO : Refactor code +# @@Other : N/A +# @@Resource : N/A +# @@Terminal App : yes +# @@sudo/root : yes +# @@Template : templates/dockerfiles/dotenv.template +# - - - - - - - - - - - - - - - - - - - - - - - - - +# shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329 +# - - - - - - - - - - - - - - - - - - - - - - - - - +# entrypoint Settings +DOCKER_ENTYPOINT_PORTS_WEB="${DOCKER_ENTYPOINT_PORTS_WEB}" +DOCKER_ENTYPOINT_PORTS_SRV="${DOCKER_ENTYPOINT_PORTS_SRV}" +DOCKER_ENTYPOINT_HEALTH_APPS="$DOCKER_ENTYPOINT_HEALTH_APPS" +DOCKER_ENTYPOINT_HEALTH_ENDPOINTS="$DOCKER_ENTYPOINT_HEALTH_ENDPOINTS" +# - - - - - - - - - - - - - - - - - - - - - - - - - +# Dockerfile info +ENV_DOCKERFILE="Dockerfile" +ENV_IMAGE_NAME="windows" +ENV_USE_TEMPLATE="alpine" +# - - - - - - - - - - - - - - - - - - - - - - - - - +# Maintainer info +ENV_ORG_NAME="casjaysdevdocker" +ENV_VENDOR="CasjaysDev" +ENV_AUTHOR="CasjaysDev" +ENV_MAINTAINER="CasjaysDev " +# - - - - - - - - - - - - - - - - - - - - - - - - - +# Repository URLs (Full URLs) +# ENV_GIT_REPO_URL: Complete Git repository URL for source code +ENV_GIT_REPO_URL="https://github.com/casjaysdevdocker/windows" +# ENV_REGISTRY_URL: Complete registry URL for reference (NOT used for pushing) +ENV_REGISTRY_URL="https://hub.docker.com/casjaysdevdocker/windows" +# - - - - - - - - - - - - - - - - - - - - - - - - - +# Push Configuration +# ENV_IMAGE_PUSH: Complete push destination (this IS used for pushing) +ENV_IMAGE_PUSH="casjaysdevdocker/windows" +# ENV_IMAGE_TAG: Default tag for the image +ENV_IMAGE_TAG="latest" +# ENV_ADD_TAGS: Additional tags, comma-separated (USE_DATE = auto date tag) +ENV_ADD_TAGS="" +# - - - - - - - - - - - - - - - - - - - - - - - - - +# Additional push destinations (if needed) +ENV_ADD_IMAGE_PUSH="" +# - - - - - - - - - - - - - - - - - - - - - - - - - +# Pull Configuration +# ENV_PULL_URL: Source image to pull from (base image) +ENV_PULL_URL="mcr.microsoft.com/windows/servercore" +# ENV_DISTRO_TAG: Tag for the pull source image +ENV_DISTRO_TAG="${IMAGE_VERSION}" +# - - - - - - - - - - - - - - - - - - - - - - - - - +# Env +SERVICE_PORT="" +EXPOSE_PORTS="" +# - - - - - - - - - - - - - - - - - - - - - - - - - +# IF using a lanuage such as go, php, rust, ruby, etc set the version here. +LANG_VERSION="" +# - - - - - - - - - - - - - - - - - - - - - - - - - +# Versions +PHP_VERSION="system" +NODE_VERSION="system" +NODE_MANAGER="system" +# - - - - - - - - - - - - - - - - - - - - - - - - - +# Default directories +WWW_ROOT_DIR="/usr/local/share/httpd/default" +DEFAULT_FILE_DIR="/usr/local/share/template-files" +DEFAULT_DATA_DIR="/usr/local/share/template-files/data" +DEFAULT_CONF_DIR="/usr/local/share/template-files/config" +DEFAULT_TEMPLATE_DIR="/usr/local/share/template-files/defaults" +# - - - - - - - - - - - - - - - - - - - - - - - - - +ENV_PACKAGES="" +# - - - - - - - - - - - - - - - - - - - - - - - - - +# ex: ts=2 sw=2 et filetype=sh +# - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..07f3b95 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,86 @@ +# 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 +# The above will handle all files NOT found below +# Documents +*.bibtex text diff=bibtex +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain +*.md text diff=markdown +*.mdx text diff=markdown +*.tex text diff=tex +*.adoc text +*.textile text +*.mustache text +*.csv text eol=crlf +*.tab text +*.tsv text +*.txt text +*.sql text +*.epub diff=astextplain +# Graphics +*.png binary +*.jpg binary +*.jpeg binary +*.gif binary +*.tif binary +*.tiff binary +*.ico binary +# SVG treated as text by default. +*.svg text +# If you want to treat it as binary, +# use the following line instead. +# *.svg binary +*.eps binary +# Scripts +*.bash text eol=lf +*.fish text eol=lf +*.ksh text eol=lf +*.sh text eol=lf +*.zsh text eol=lf +# These are explicitly windows files and should use crlf +*.bat text eol=crlf +*.cmd text eol=crlf +*.ps1 text eol=crlf +# Serialisation +*.json text +*.toml text +*.xml text +*.yaml text +*.yml text +# Archives +*.7z binary +*.bz binary +*.bz2 binary +*.bzip2 binary +*.gz binary +*.lz binary +*.lzma binary +*.rar binary +*.tar binary +*.taz binary +*.tbz binary +*.tbz2 binary +*.tgz binary +*.tlz binary +*.txz binary +*.xz binary +*.Z binary +*.zip binary +*.zst binary +# Text files where line endings should be preserved +*.patch -text +# Exclude files from exporting +.gitattributes export-ignore +.gitignore export-ignore +.gitkeep export-ignore + diff --git a/.gitea/workflows/docker.yaml b/.gitea/workflows/docker.yaml new file mode 100644 index 0000000..0601d57 --- /dev/null +++ b/.gitea/workflows/docker.yaml @@ -0,0 +1,60 @@ +name: windows + +on: push + +jobs: + release-windows: + runs-on: act_runner + container: + image: catthehacker/ubuntu:act-latest + env: + RUNNER_TOOL_CACHE: /toolcache + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + + - 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" + + - name: Set up Docker BuildX + uses: docker/setup-buildx-action@v2 + + - name: Login to DockerHub + uses: docker/login-action@v2 + with: + password: ${{ secrets.DOCKER_TOKEN }} + username: ${{ secrets.DOCKER_USERNAME }} + registry: ${{ steps.meta.outputs.DOCKER_HUB }} + + - name: Build and push + uses: docker/build-push-action@v4 + with: + context: . + file: ./Dockerfile + platforms: | + linux/amd64 + linux/arm64 + push: true + build-args: | + IMAGE_NAME=${{ steps.meta.outputs.REPO_NAME }} + BUILD_DATE=$(date -u +'%Y%m%d%H%M') + BUILD_VERSION=$(date -u +'%Y%m%d%H%M') + GIT_COMMIT=${{ github.sha }} + TIMEZONE=America/New_York + LANGUAGE=en_US.UTF-8 + LICENSE=WTFPL + TZ=America/New_York + 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 }} diff --git a/.github/workflows/README.md b/.github/workflows/README.md new file mode 100644 index 0000000..f75d539 --- /dev/null +++ b/.github/workflows/README.md @@ -0,0 +1,130 @@ +# GitHub Actions Workflow for Windows Container + +This workflow **fully automates** building Windows Server Core containers using GitHub Actions variables. + +## 🤖 Fully Automated Setup + +### 1. Set Variables (One-time setup) + +**Settings → Secrets and variables → Actions → Variables tab → New repository variable** + +Add this variable: +- `DOCKER_USERNAME` - Your Docker Hub username (e.g., `casjaysdevdocker`) + +**Settings → Secrets and variables → Actions → Secrets tab → New repository secret** + +Add this secret: +- `DOCKER_PASSWORD` - Your Docker Hub password or access token + +### 2. That's It! 🎉 + +The workflow automatically: +- ✅ Builds on every push to main/master/develop +- ✅ Builds monthly (1st of month at 2 AM UTC) +- ✅ Auto-detects repo name from GitHub +- ✅ Auto-generates image name: `/` +- ✅ Auto-creates tags: `latest` and `YYMM` format +- ✅ Auto-extracts metadata from git +- ✅ Auto-pushes to Docker Hub (if credentials set) +- ✅ Creates build summary in Actions tab + +## 🏷️ Automatic Image Tags + +**Format**: `/:` + +Examples for January 2026: +- `casjaysdevdocker/windows:latest` +- `casjaysdevdocker/windows:2601` + +## ⚙️ Automatic Metadata + +All OCI labels and annotations automatically include: +- Build date and time +- Git commit hash (short) +- Repository URL from GitHub +- Docker Hub URL +- Version (YYMM format) + +## 🔄 When Builds Run + +1. **On Push** - Any push to main/master/develop branches +2. **On Pull Request** - Tests build but doesn't push +3. **Monthly** - Automatic rebuild on 1st of each month at 2 AM UTC +4. **Manual** - Click "Run workflow" in Actions tab + +## 📊 Build Summary + +After each successful build, check the Actions tab for: +- Image name and tags +- Build date and commit +- Pull command +- Image size +- All metadata labels + +## 🚫 No Variables? No Problem! + +If `DOCKER_USERNAME` variable is not set: +- Falls back to repository owner name +- Example: `owner/windows:latest` + +If `DOCKER_PASSWORD` secret is not set: +- Build and test still run +- Push step is automatically skipped +- Perfect for testing or forked repos + +## 📝 Example Output + +``` +## 📦 Container Build Summary + +**Image:** `casjaysdevdocker/windows` +**Tags:** +- `latest` +- `2601` + +**Build Date:** 202601231800 +**Commit:** `a1b2c3d` + +### 🚀 Pull Command +```powershell +docker pull casjaysdevdocker/windows:latest +``` + +## 🔧 Advanced: Override Image Name + +Want to use a different Docker Hub username? Just set the variable: + +**Settings → Secrets and variables → Actions → Variables** +- `DOCKER_USERNAME` = `yourusername` + +Result: `yourusername/windows:latest` + +## 🛠️ Troubleshooting + +### Build succeeds but doesn't push +- Check that `DOCKER_PASSWORD` secret is set +- Verify `DOCKER_USERNAME` variable or repo owner is correct +- Ensure you're not building from a pull request + +### Wrong image name +- Set `DOCKER_USERNAME` variable to your Docker Hub username +- Or it defaults to GitHub repo owner + +### Need different tags? +- Edit `.github/workflows/build-windows.yml` +- Modify the `TAG_YYMM` format in the metadata step + +## 📅 Monthly Auto-Build + +The workflow includes a cron schedule: +```yaml +schedule: + - cron: '0 2 1 * *' # 1st of month at 2 AM UTC +``` + +This ensures: +- Fresh base image updates +- Latest security patches +- Regular image rebuilds + +To disable: Remove the `schedule:` section from the workflow file. diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml new file mode 100644 index 0000000..70069e1 --- /dev/null +++ b/.github/workflows/build-windows.yml @@ -0,0 +1,176 @@ +name: Build Windows Container + +on: + push: + branches: + - main + - master + - develop + pull_request: + branches: + - main + - master + workflow_dispatch: + schedule: + - cron: '0 2 1 * *' # Build monthly on 1st at 2 AM UTC + +env: + REGISTRY: docker.io + +jobs: + build: + runs-on: windows-2022 + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Extract metadata + id: meta + run: | + $BUILD_DATE = Get-Date -Format "yyyyMMddHHmm" + $TAG_YYMM = Get-Date -Format "yyMM" + $GIT_COMMIT = $env:GITHUB_SHA.Substring(0,7) + + # Extract repo name from GITHUB_REPOSITORY (owner/repo) + $REPO_NAME = $env:GITHUB_REPOSITORY.Split('/')[1] + + # Get Docker username from variables, fallback to repo owner + $DOCKER_USER = "${{ vars.DOCKER_USERNAME }}" + if ([string]::IsNullOrWhiteSpace($DOCKER_USER)) { + $DOCKER_USER = $env:GITHUB_REPOSITORY.Split('/')[0] + } + + $IMAGE_NAME = "$DOCKER_USER/$REPO_NAME" + + echo "BUILD_DATE=$BUILD_DATE" >> $env:GITHUB_ENV + echo "TAG_YYMM=$TAG_YYMM" >> $env:GITHUB_ENV + echo "GIT_COMMIT=$GIT_COMMIT" >> $env:GITHUB_ENV + echo "IMAGE_NAME=$IMAGE_NAME" >> $env:GITHUB_ENV + echo "REPO_NAME=$REPO_NAME" >> $env:GITHUB_ENV + + Write-Host "Image Name: $IMAGE_NAME" + Write-Host "Build Date: $BUILD_DATE" + Write-Host "Tag YYMM: $TAG_YYMM" + Write-Host "Git Commit: $GIT_COMMIT" + shell: powershell + + - name: Build Docker image with annotations + run: | + docker build ` + --build-arg BUILD_DATE=$env:BUILD_DATE ` + --build-arg GIT_COMMIT=$env:GIT_COMMIT ` + --label "maintainer=CasjaysDev " ` + --label "org.opencontainers.image.vendor=CasjaysDev" ` + --label "org.opencontainers.image.authors=CasjaysDev" ` + --label "org.opencontainers.image.description=Containerized version of $env:REPO_NAME" ` + --label "org.opencontainers.image.title=$env:REPO_NAME" ` + --label "org.opencontainers.image.base.name=$env:REPO_NAME" ` + --label "org.opencontainers.image.licenses=WTFPL" ` + --label "org.opencontainers.image.created=$env:BUILD_DATE" ` + --label "org.opencontainers.image.version=$env:TAG_YYMM" ` + --label "org.opencontainers.image.url=https://hub.docker.com/r/$env:IMAGE_NAME" ` + --label "org.opencontainers.image.source=$env:GITHUB_SERVER_URL/$env:GITHUB_REPOSITORY" ` + --label "org.opencontainers.image.vcs-type=Git" ` + --label "org.opencontainers.image.revision=$env:GIT_COMMIT" ` + --label "org.opencontainers.image.documentation=$env:GITHUB_SERVER_URL/$env:GITHUB_REPOSITORY" ` + --label "com.github.containers.toolbox=false" ` + --annotation "maintainer=CasjaysDev " ` + --annotation "org.opencontainers.image.vendor=CasjaysDev" ` + --annotation "org.opencontainers.image.authors=CasjaysDev" ` + --annotation "org.opencontainers.image.description=Containerized version of $env:REPO_NAME" ` + --annotation "org.opencontainers.image.title=$env:REPO_NAME" ` + --annotation "org.opencontainers.image.base.name=$env:REPO_NAME" ` + --annotation "org.opencontainers.image.licenses=WTFPL" ` + --annotation "org.opencontainers.image.created=$env:BUILD_DATE" ` + --annotation "org.opencontainers.image.version=$env:TAG_YYMM" ` + --annotation "org.opencontainers.image.url=https://hub.docker.com/r/$env:IMAGE_NAME" ` + --annotation "org.opencontainers.image.source=$env:GITHUB_SERVER_URL/$env:GITHUB_REPOSITORY" ` + --annotation "org.opencontainers.image.vcs-type=Git" ` + --annotation "org.opencontainers.image.revision=$env:GIT_COMMIT" ` + --annotation "org.opencontainers.image.documentation=$env:GITHUB_SERVER_URL/$env:GITHUB_REPOSITORY" ` + --annotation "com.github.containers.toolbox=false" ` + --tag $env:IMAGE_NAME`:latest ` + --tag $env:IMAGE_NAME`:$env:TAG_YYMM ` + . + shell: powershell + + - name: Test container + run: | + Write-Host "Starting container for testing..." + docker run -d --name test-container $env:IMAGE_NAME`:latest + Start-Sleep -Seconds 10 + + Write-Host "Checking container health..." + docker ps -a + + $containerStatus = docker inspect test-container --format='{{.State.Status}}' + Write-Host "Container status: $containerStatus" + + if ($containerStatus -ne "running") { + Write-Host "Container logs:" + docker logs test-container + exit 1 + } + + Write-Host "Testing healthcheck..." + docker exec test-container powershell -Command "C:/Windows/System32/entrypoint.ps1 healthcheck" + + Write-Host "Stopping test container..." + docker stop test-container + docker rm test-container + shell: powershell + + - name: Login to Docker Hub + if: github.event_name != 'pull_request' && secrets.DOCKER_PASSWORD != '' + uses: docker/login-action@v3 + with: + username: ${{ vars.DOCKER_USERNAME || github.repository_owner }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Push to Docker Hub + if: github.event_name != 'pull_request' && secrets.DOCKER_PASSWORD != '' + run: | + Write-Host "Pushing $env:IMAGE_NAME`:latest..." + docker push $env:IMAGE_NAME`:latest + + Write-Host "Pushing $env:IMAGE_NAME`:$env:TAG_YYMM..." + docker push $env:IMAGE_NAME`:$env:TAG_YYMM + + Write-Host "=== Images pushed successfully ===" + Write-Host "Latest: $env:IMAGE_NAME`:latest" + Write-Host "Monthly: $env:IMAGE_NAME`:$env:TAG_YYMM" + shell: powershell + + - name: Image details + if: always() + run: | + Write-Host "=== Built Images ===" + docker images $env:IMAGE_NAME + + Write-Host "`n=== Image Labels ===" + docker inspect $env:IMAGE_NAME`:latest --format='{{json .Config.Labels}}' | ConvertFrom-Json | Format-List + + Write-Host "`n=== Image Size ===" + $size = docker images $env:IMAGE_NAME`:latest --format='{{.Size}}' + Write-Host "Image size: $size" + shell: powershell + + - name: Create release summary + if: github.event_name != 'pull_request' + run: | + Write-Host "## 📦 Container Build Summary" >> $env:GITHUB_STEP_SUMMARY + Write-Host "" >> $env:GITHUB_STEP_SUMMARY + Write-Host "**Image:** ``$env:IMAGE_NAME``" >> $env:GITHUB_STEP_SUMMARY + Write-Host "**Tags:**" >> $env:GITHUB_STEP_SUMMARY + Write-Host "- ``latest``" >> $env:GITHUB_STEP_SUMMARY + Write-Host "- ``$env:TAG_YYMM``" >> $env:GITHUB_STEP_SUMMARY + Write-Host "" >> $env:GITHUB_STEP_SUMMARY + Write-Host "**Build Date:** $env:BUILD_DATE" >> $env:GITHUB_STEP_SUMMARY + Write-Host "**Commit:** ``$env:GIT_COMMIT``" >> $env:GITHUB_STEP_SUMMARY + Write-Host "" >> $env:GITHUB_STEP_SUMMARY + Write-Host "### 🚀 Pull Command" >> $env:GITHUB_STEP_SUMMARY + Write-Host '```powershell' >> $env:GITHUB_STEP_SUMMARY + Write-Host "docker pull $env:IMAGE_NAME`:latest" >> $env:GITHUB_STEP_SUMMARY + Write-Host '```' >> $env:GITHUB_STEP_SUMMARY + shell: powershell diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f414ea5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,104 @@ +# gitignore created on 01/23/26 at 13:10 +# Disable reminder in prompt +ignoredirmessage + +# ignore .build_failed files +**/.build_failed* + +# OS generated files +### Linux ### +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +### macOS ### +# General +.DS_Store? +.AppleDouble +.LSOverride + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### macOS Patch ### +# iCloud generated files +*.icloud + +### Windows ### +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# misc +!*/README* +!inc/main.bash + +# Windows shortcuts +*.lnk + +# ignore commit message +**/.gitcommit + +# ignore .build_failed files +**/.build_failed* + +# ignore .bak files +**/*.bak + +# ignore .no_push files +**/.no_push + +# ignore .no_git files +**/.no_git + +# ignore .installed files +**/.installed + +# ignore work in progress files +**/*.rewrite.sh +**/*.refactor.sh + diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..4c71a91 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,228 @@ +# Docker image for windows using Windows Server Core +ARG IMAGE_NAME="windows" +ARG PHP_SERVER="windows" +ARG BUILD_DATE="202601231310" +ARG LANGUAGE="en-US" +ARG TIMEZONE="Eastern Standard Time" +ARG WWW_ROOT_DIR="C:/inetpub/wwwroot" +ARG DEFAULT_FILE_DIR="C:/ProgramData/template-files" +ARG DEFAULT_DATA_DIR="C:/ProgramData/template-files/data" +ARG DEFAULT_CONF_DIR="C:/ProgramData/template-files/config" +ARG DEFAULT_TEMPLATE_DIR="C:/ProgramData/template-files/defaults" + +ARG USER="Administrator" +ARG SHELL_OPTS="" + +ARG SERVICE_PORT="" +ARG EXPOSE_PORTS="" +ARG PHP_VERSION="system" +ARG NODE_VERSION="system" +ARG NODE_MANAGER="system" + +ARG IMAGE_REPO="casjaysdevdocker/windows" +ARG IMAGE_VERSION="ltsc2022" +ARG CONTAINER_VERSION="" + +ARG PULL_URL="mcr.microsoft.com/windows/servercore" +ARG DISTRO_VERSION="${IMAGE_VERSION}" +ARG BUILD_VERSION="${BUILD_DATE}" + +FROM ${PULL_URL}:${DISTRO_VERSION} AS build +ARG TZ +ARG USER +ARG LICENSE +ARG TIMEZONE +ARG LANGUAGE +ARG IMAGE_NAME +ARG BUILD_DATE +ARG SERVICE_PORT +ARG EXPOSE_PORTS +ARG BUILD_VERSION +ARG IMAGE_VERSION +ARG WWW_ROOT_DIR +ARG DEFAULT_FILE_DIR +ARG DEFAULT_DATA_DIR +ARG DEFAULT_CONF_DIR +ARG DEFAULT_TEMPLATE_DIR +ARG DISTRO_VERSION +ARG NODE_VERSION +ARG NODE_MANAGER +ARG PHP_VERSION +ARG PHP_SERVER +ARG SHELL_OPTS +ARG PATH + +ARG PACK_LIST=" " + +ENV TIMEZONE="${TIMEZONE}" +ENV LANG="${LANGUAGE}" +ENV HOSTNAME="casjaysdevdocker-windows" + +USER ${USER} +WORKDIR C:/Users/Administrator + +SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"] + +COPY ./rootfs/. C:/ + +RUN Write-Host 'Setting up prerequisites'; \ + New-Item -ItemType Directory -Force -Path $env:DEFAULT_DATA_DIR, $env:DEFAULT_CONF_DIR, $env:DEFAULT_TEMPLATE_DIR, 'C:/ProgramData/Docker/setup' | Out-Null + +RUN Write-Host 'Initializing the system'; \ + if (Test-Path 'C:/ProgramData/Docker/setup/00-init.ps1') { \ + Write-Host 'Running the init script'; \ + & 'C:/ProgramData/Docker/setup/00-init.ps1'; \ + if ($LASTEXITCODE -ne 0) { Write-Error 'Failed to execute 00-init.ps1'; exit 10 }; \ + Write-Host 'Done running the init script'; \ + } + +RUN Write-Host 'Creating and editing system files'; \ + if (Test-Path 'C:/ProgramData/Docker/setup/01-system.ps1') { \ + Write-Host 'Running the system script'; \ + & 'C:/ProgramData/Docker/setup/01-system.ps1'; \ + if ($LASTEXITCODE -ne 0) { Write-Error 'Failed to execute 01-system.ps1'; exit 10 }; \ + Write-Host 'Done running the system script'; \ + } + +RUN Write-Host 'Running pre-package commands' + +RUN Write-Host 'Setting up and installing packages'; \ + if ($env:PACK_LIST -and $env:PACK_LIST.Trim() -ne '') { \ + Write-Host "Installing packages: $env:PACK_LIST"; \ + $env:PACK_LIST | Out-File -FilePath 'C:/ProgramData/Docker/setup/packages.txt' -Encoding UTF8; \ + & 'C:/Windows/System32/pkmgr.ps1' install $env:PACK_LIST.Split(' '); \ + } + +RUN Write-Host 'Initializing packages before copying files to image'; \ + if (Test-Path 'C:/ProgramData/Docker/setup/02-packages.ps1') { \ + Write-Host 'Running the packages script'; \ + & 'C:/ProgramData/Docker/setup/02-packages.ps1'; \ + if ($LASTEXITCODE -ne 0) { Write-Error 'Failed to execute 02-packages.ps1'; exit 10 }; \ + Write-Host 'Done running the packages script'; \ + } + +COPY ./Dockerfile C:/ProgramData/Docker/Dockerfile + +RUN Write-Host 'Updating system files'; \ + if (Test-Path 'C:/ProgramData/Docker/setup/03-files.ps1') { \ + Write-Host 'Running the files script'; \ + & 'C:/ProgramData/Docker/setup/03-files.ps1'; \ + if ($LASTEXITCODE -ne 0) { Write-Error 'Failed to execute 03-files.ps1'; exit 10 }; \ + Write-Host 'Done running the files script'; \ + } + +RUN Write-Host 'Custom Settings' + +RUN Write-Host 'Setting up users and scripts'; \ + if (Test-Path 'C:/ProgramData/Docker/setup/04-users.ps1') { \ + Write-Host 'Running the users script'; \ + & 'C:/ProgramData/Docker/setup/04-users.ps1'; \ + if ($LASTEXITCODE -ne 0) { Write-Error 'Failed to execute 04-users.ps1'; exit 10 }; \ + Write-Host 'Done running the users script'; \ + } + +RUN Write-Host 'Running the user init commands' + +RUN Write-Host 'Setting OS Settings' + +RUN Write-Host 'Custom Applications' + +RUN Write-Host 'Running custom commands'; \ + if (Test-Path 'C:/ProgramData/Docker/setup/05-custom.ps1') { \ + Write-Host 'Running the custom script'; \ + & 'C:/ProgramData/Docker/setup/05-custom.ps1'; \ + if ($LASTEXITCODE -ne 0) { Write-Error 'Failed to execute 05-custom.ps1'; exit 10 }; \ + Write-Host 'Done running the custom script'; \ + } + +RUN Write-Host 'Running final commands before cleanup'; \ + if (Test-Path 'C:/ProgramData/Docker/setup/06-post.ps1') { \ + Write-Host 'Running the post script'; \ + & 'C:/ProgramData/Docker/setup/06-post.ps1'; \ + if ($LASTEXITCODE -ne 0) { Write-Error 'Failed to execute 06-post.ps1'; exit 10 }; \ + Write-Host 'Done running the post script'; \ + } + +RUN Write-Host 'Deleting unneeded files'; \ + & 'C:/Windows/System32/pkmgr.ps1' clean; \ + Remove-Item -Path 'C:/config', 'C:/data' -Recurse -Force -ErrorAction SilentlyContinue; \ + if (Test-Path 'C:/ProgramData/Docker/setup/07-cleanup.ps1') { \ + Write-Host 'Running the cleanup script'; \ + & 'C:/ProgramData/Docker/setup/07-cleanup.ps1'; \ + if ($LASTEXITCODE -ne 0) { Write-Error 'Failed to execute 07-cleanup.ps1'; exit 10 }; \ + Write-Host 'Done running the cleanup script'; \ + } + +RUN Write-Host 'Init done' + +FROM mcr.microsoft.com/windows/servercore:ltsc2022 +ARG TZ +ARG PATH +ARG USER +ARG TIMEZONE +ARG LANGUAGE +ARG IMAGE_NAME +ARG BUILD_DATE +ARG SERVICE_PORT +ARG EXPOSE_PORTS +ARG BUILD_VERSION +ARG IMAGE_VERSION +ARG GIT_COMMIT +ARG WWW_ROOT_DIR +ARG DEFAULT_FILE_DIR +ARG DEFAULT_DATA_DIR +ARG DEFAULT_CONF_DIR +ARG DEFAULT_TEMPLATE_DIR +ARG DISTRO_VERSION +ARG NODE_VERSION +ARG NODE_MANAGER +ARG PHP_VERSION +ARG PHP_SERVER +ARG LICENSE="WTFPL" +ARG ENV_PORTS="${EXPOSE_PORTS}" + +USER ${USER} +WORKDIR C:/Users/Administrator + +LABEL maintainer="CasjaysDev " +LABEL org.opencontainers.image.vendor="CasjaysDev" +LABEL org.opencontainers.image.authors="CasjaysDev" +LABEL org.opencontainers.image.description="Containerized version of ${IMAGE_NAME}" +LABEL org.opencontainers.image.title="${IMAGE_NAME}" +LABEL org.opencontainers.image.base.name="${IMAGE_NAME}" +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/windows" +LABEL org.opencontainers.image.source="https://hub.docker.com/casjaysdevdocker/windows" +LABEL org.opencontainers.image.vcs-type="Git" +LABEL org.opencontainers.image.revision="${GIT_COMMIT}" +LABEL org.opencontainers.image.source="https://github.com/casjaysdevdocker/windows" +LABEL org.opencontainers.image.documentation="https://github.com/casjaysdevdocker/windows" +LABEL com.github.containers.toolbox="false" + +ENV USER="${USER}" +ENV TIMEZONE="${TIMEZONE}" +ENV LANG="${LANGUAGE}" +ENV PORT="${SERVICE_PORT}" +ENV ENV_PORTS="${ENV_PORTS}" +ENV CONTAINER_NAME="${IMAGE_NAME}" +ENV HOSTNAME="casjaysdev-${IMAGE_NAME}" +ENV PHP_SERVER="${PHP_SERVER}" +ENV NODE_VERSION="${NODE_VERSION}" +ENV NODE_MANAGER="${NODE_MANAGER}" +ENV PHP_VERSION="${PHP_VERSION}" +ENV DISTRO_VERSION="${IMAGE_VERSION}" +ENV WWW_ROOT_DIR="${WWW_ROOT_DIR}" + +SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"] + +COPY --from=build C:/ C:/ + +VOLUME ["C:/config", "C:/data"] + +EXPOSE ${SERVICE_PORT} ${ENV_PORTS} + +ENTRYPOINT ["powershell", "-File", "C:/Windows/System32/entrypoint.ps1"] +HEALTHCHECK --start-period=10m --interval=5m --timeout=15s CMD powershell -File C:/Windows/System32/entrypoint.ps1 healthcheck diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..27b62a2 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,13 @@ + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + Version 2, December 2004 + + Copyright (C) 2026 casjay + + Everyone is permitted to copy and distribute verbatim or modified + copies of this license document, and changing it is allowed as long + as the name is changed. + + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 1. You just DO WHAT THE FUCK YOU WANT TO. diff --git a/README.md b/README.md new file mode 100644 index 0000000..3896a2e --- /dev/null +++ b/README.md @@ -0,0 +1,106 @@ +## 👋 Welcome to windows 🚀 + +Windows Server Core Container for running Windows applications in Docker. + +⚠️ **IMPORTANT**: This container requires a Windows host to build and run. It will NOT work on Linux or macOS. + +## Requirements + +- Windows Server 2022 or Windows 10/11 Pro with containers feature enabled +- Docker Desktop for Windows (with Windows containers enabled) +- At least 10GB free disk space for the image + +## Install and run container + +```powershell +# Create directories +$dockerHome = "C:\docker\casjaysdevdocker\windows" +New-Item -ItemType Directory -Force -Path "$dockerHome\data", "$dockerHome\config" + +# Run container +docker run -d ` + --restart always ` + --name casjaysdevdocker-windows-latest ` + --hostname windows ` + -e TIMEZONE="Eastern Standard Time" ` + -v "$dockerHome\data:C:\data" ` + -v "$dockerHome\config:C:\config" ` + -p 80:80 ` + casjaysdevdocker/windows:latest +``` + +## via docker-compose + +```yaml +version: "3.8" +services: + windows: + image: casjaysdevdocker/windows:latest + container_name: casjaysdevdocker-windows + environment: + - TIMEZONE=Eastern Standard Time + - HOSTNAME=windows + volumes: + - "C:/docker/casjaysdevdocker/windows/data:C:/data" + - "C:/docker/casjaysdevdocker/windows/config:C:/config" + ports: + - "80:80" + restart: always +``` + +## Get source files + +```powershell +git clone "https://github.com/casjaysdevdocker/windows" "$env:USERPROFILE\Projects\casjaysdevdocker\windows" +``` + +## Build container + +⚠️ **Must be built on Windows with Docker Desktop in Windows containers mode** + +```powershell +cd "$env:USERPROFILE\Projects\casjaysdevdocker\windows" +docker build -t casjaysdevdocker/windows:latest . +``` + +## Package Management + +This container uses **winget** (Windows Package Manager) or **chocolatey** as fallback. To install packages: + +```powershell +# Via pkmgr wrapper (recommended) +docker exec casjaysdevdocker-windows-latest powershell "C:/Windows/System32/pkmgr.ps1 install git.git" +docker exec casjaysdevdocker-windows-latest powershell "C:/Windows/System32/pkmgr.ps1 install nodejs" + +# Direct via winget +docker exec casjaysdevdocker-windows-latest powershell "winget install git.git" +``` + +## Container Structure + +``` +C:/ +├── ProgramData/ +│ ├── Docker/setup/ - Setup scripts (00-init.ps1 to 07-cleanup.ps1) +│ └── template-files/ - Configuration templates +├── Windows/System32/ +│ ├── entrypoint.ps1 - Container entrypoint +│ ├── pkmgr.ps1 - Package manager wrapper +│ └── pkmgr - Shell script version +├── Users/Administrator/ - User home directory +├── config/ - Configuration volume mount +└── data/ - Data volume mount +``` + +## Environment Variables + +- `TIMEZONE` - Windows timezone (default: "Eastern Standard Time") +- `HOSTNAME` - Container hostname +- `LANG` - Language setting (default: "en-US") +- `SERVICE_PORT` - Primary service port +- `ENV_PORTS` - Additional exposed ports + +## Authors + +🤖 casjay: [Github](https://github.com/casjay) 🤖 +⛵ casjaysdevdocker: [Github](https://github.com/casjaysdevdocker) [Docker](https://hub.docker.com/u/casjaysdevdocker) ⛵ diff --git a/rootfs/ProgramData/Docker/setup/00-init.ps1 b/rootfs/ProgramData/Docker/setup/00-init.ps1 new file mode 100644 index 0000000..0b4f1b2 --- /dev/null +++ b/rootfs/ProgramData/Docker/setup/00-init.ps1 @@ -0,0 +1,26 @@ +# PowerShell script for Windows container initialization +# @Version: 202601231310-git +# @Author: CasjaysDev +# @Contact: CasjaysDev +# @License: MIT +# @Copyright: Copyright 2026 CasjaysDev +# @File: 00-init.ps1 +# @Description: Script to run init + +$ErrorActionPreference = 'Stop' +$exitCode = 0 + +# Predefined actions - Clear template directories +if (Test-Path 'C:/ProgramData/template-files/data') { + Get-ChildItem 'C:/ProgramData/template-files/data' -Recurse -ErrorAction SilentlyContinue | Remove-Item -Force -Recurse -ErrorAction SilentlyContinue +} +if (Test-Path 'C:/ProgramData/template-files/config') { + Get-ChildItem 'C:/ProgramData/template-files/config' -Recurse -ErrorAction SilentlyContinue | Remove-Item -Force -Recurse -ErrorAction SilentlyContinue +} +if (Test-Path 'C:/ProgramData/template-files/defaults') { + Get-ChildItem 'C:/ProgramData/template-files/defaults' -Recurse -ErrorAction SilentlyContinue | Remove-Item -Force -Recurse -ErrorAction SilentlyContinue +} + +# Main script logic here + +exit $exitCode diff --git a/rootfs/ProgramData/Docker/setup/01-system.ps1 b/rootfs/ProgramData/Docker/setup/01-system.ps1 new file mode 100644 index 0000000..7bae0ac --- /dev/null +++ b/rootfs/ProgramData/Docker/setup/01-system.ps1 @@ -0,0 +1,15 @@ +# PowerShell script for Windows container system setup +# @Version: 202601231310-git +# @Author: CasjaysDev +# @Contact: CasjaysDev +# @License: MIT +# @Copyright: Copyright 2026 CasjaysDev +# @File: 01-system.ps1 +# @Description: Script to run system setup + +$ErrorActionPreference = 'Stop' +$exitCode = 0 + +# System configuration here + +exit $exitCode diff --git a/rootfs/ProgramData/Docker/setup/02-packages.ps1 b/rootfs/ProgramData/Docker/setup/02-packages.ps1 new file mode 100644 index 0000000..21b4d38 --- /dev/null +++ b/rootfs/ProgramData/Docker/setup/02-packages.ps1 @@ -0,0 +1,15 @@ +# PowerShell script for Windows container package setup +# @Version: 202601231310-git +# @Author: CasjaysDev +# @Contact: CasjaysDev +# @License: MIT +# @Copyright: Copyright 2026 CasjaysDev +# @File: 02-packages.ps1 +# @Description: Script to run package initialization + +$ErrorActionPreference = 'Stop' +$exitCode = 0 + +# Package initialization here + +exit $exitCode diff --git a/rootfs/ProgramData/Docker/setup/03-files.ps1 b/rootfs/ProgramData/Docker/setup/03-files.ps1 new file mode 100644 index 0000000..2189a59 --- /dev/null +++ b/rootfs/ProgramData/Docker/setup/03-files.ps1 @@ -0,0 +1,15 @@ +# PowerShell script for Windows container files setup +# @Version: 202601231310-git +# @Author: CasjaysDev +# @Contact: CasjaysDev +# @License: MIT +# @Copyright: Copyright 2026 CasjaysDev +# @File: 03-files.ps1 +# @Description: Script to configure system files + +$ErrorActionPreference = 'Stop' +$exitCode = 0 + +# File configuration here + +exit $exitCode diff --git a/rootfs/ProgramData/Docker/setup/04-users.ps1 b/rootfs/ProgramData/Docker/setup/04-users.ps1 new file mode 100644 index 0000000..ff5575a --- /dev/null +++ b/rootfs/ProgramData/Docker/setup/04-users.ps1 @@ -0,0 +1,15 @@ +# PowerShell script for Windows container user setup +# @Version: 202601231310-git +# @Author: CasjaysDev +# @Contact: CasjaysDev +# @License: MIT +# @Copyright: Copyright 2026 CasjaysDev +# @File: 04-users.ps1 +# @Description: Script to configure users + +$ErrorActionPreference = 'Stop' +$exitCode = 0 + +# User configuration here + +exit $exitCode diff --git a/rootfs/ProgramData/Docker/setup/05-custom.ps1 b/rootfs/ProgramData/Docker/setup/05-custom.ps1 new file mode 100644 index 0000000..ed61307 --- /dev/null +++ b/rootfs/ProgramData/Docker/setup/05-custom.ps1 @@ -0,0 +1,15 @@ +# PowerShell script for Windows container custom setup +# @Version: 202601231310-git +# @Author: CasjaysDev +# @Contact: CasjaysDev +# @License: MIT +# @Copyright: Copyright 2026 CasjaysDev +# @File: 05-custom.ps1 +# @Description: Script for custom configurations + +$ErrorActionPreference = 'Stop' +$exitCode = 0 + +# Custom configuration here + +exit $exitCode diff --git a/rootfs/ProgramData/Docker/setup/06-post.ps1 b/rootfs/ProgramData/Docker/setup/06-post.ps1 new file mode 100644 index 0000000..b3ba634 --- /dev/null +++ b/rootfs/ProgramData/Docker/setup/06-post.ps1 @@ -0,0 +1,15 @@ +# PowerShell script for Windows container post setup +# @Version: 202601231310-git +# @Author: CasjaysDev +# @Contact: CasjaysDev +# @License: MIT +# @Copyright: Copyright 2026 CasjaysDev +# @File: 06-post.ps1 +# @Description: Script for post-installation tasks + +$ErrorActionPreference = 'Stop' +$exitCode = 0 + +# Post-installation tasks here + +exit $exitCode diff --git a/rootfs/ProgramData/Docker/setup/07-cleanup.ps1 b/rootfs/ProgramData/Docker/setup/07-cleanup.ps1 new file mode 100644 index 0000000..c8f3da0 --- /dev/null +++ b/rootfs/ProgramData/Docker/setup/07-cleanup.ps1 @@ -0,0 +1,23 @@ +# PowerShell script for Windows container cleanup +# @Version: 202601231310-git +# @Author: CasjaysDev +# @Contact: CasjaysDev +# @License: MIT +# @Copyright: Copyright 2026 CasjaysDev +# @File: 07-cleanup.ps1 +# @Description: Script for cleanup tasks + +$ErrorActionPreference = 'Stop' +$exitCode = 0 + +# Clean Windows temp files +Remove-Item -Path 'C:\Windows\Temp\*' -Recurse -Force -ErrorAction SilentlyContinue +Remove-Item -Path 'C:\Users\*\AppData\Local\Temp\*' -Recurse -Force -ErrorAction SilentlyContinue + +# Clean package caches +if (Get-Command winget -ErrorAction SilentlyContinue) { + # Winget doesn't have explicit cache clean yet + Write-Host 'Winget cache management' +} + +exit $exitCode diff --git a/rootfs/Windows/System32/entrypoint.ps1 b/rootfs/Windows/System32/entrypoint.ps1 new file mode 100644 index 0000000..a8758cd --- /dev/null +++ b/rootfs/Windows/System32/entrypoint.ps1 @@ -0,0 +1,101 @@ +# PowerShell entrypoint for Windows container +# @Version: 202601231310-git +# @Author: CasjaysDev +# @Contact: CasjaysDev +# @License: WTFPL +# @Copyright: Copyright (c) 2026 Jason Hempstead, Casjays Developments +# @File: entrypoint.ps1 +# @Description: Entrypoint file for windows container + +param( + [string]$Command = "" +) + +$ErrorActionPreference = 'Stop' +$SERVICE_PID_FILE = "C:\ProgramData\container.pid" +$SERVICE_IS_RUNNING = "no" + +# Trap handler for cleanup +trap { + Write-Host "Container received shutdown signal" + if ($SERVICE_IS_RUNNING -ne "yes" -and (Test-Path $SERVICE_PID_FILE)) { + Remove-Item -Path $SERVICE_PID_FILE -Force -ErrorAction SilentlyContinue + } + exit 1 +} + +# Load debug configuration +if (Test-Path "C:\config\.debug") { + $env:DEBUGGER_OPTIONS = Get-Content "C:\config\.debug" -Raw +} else { + $env:DEBUGGER_OPTIONS = "" +} + +if ($env:DEBUGGER -eq "on" -or (Test-Path "C:\config\.debug")) { + $VerbosePreference = 'Continue' + $DebugPreference = 'Continue' + Write-Host "Debugging enabled" +} + +# Function to check service health +function Test-ServiceHealth { + # Add health check logic here + # Return $true if healthy, $false otherwise + return $true +} + +# Handle commands +switch ($Command.ToLower()) { + "healthcheck" { + if (Test-ServiceHealth) { + Write-Host "Service is healthy" + exit 0 + } else { + Write-Host "Service is unhealthy" + exit 1 + } + } + "version" { + Write-Host "Windows Container Version: $env:BUILD_VERSION" + Write-Host "Distro: Windows Server Core $env:DISTRO_VERSION" + exit 0 + } + default { + # Default startup behavior + Write-Host "Starting Windows container..." + Write-Host "Hostname: $env:HOSTNAME" + Write-Host "Timezone: $env:TIMEZONE" + + # Set timezone + try { + if ($env:TIMEZONE) { + & tzutil.exe /s $env:TIMEZONE + Write-Host "Timezone set to: $env:TIMEZONE" + } + } catch { + Write-Warning "Failed to set timezone: $_" + } + + # Create PID file + $PID | Out-File -FilePath $SERVICE_PID_FILE -Encoding ASCII + $global:SERVICE_IS_RUNNING = "yes" + + # Keep container running + Write-Host "Container started successfully" + Write-Host "Press Ctrl+C to stop" + + # Run any startup commands here + + # Keep alive loop + try { + while ($true) { + Start-Sleep -Seconds 60 + } + } finally { + # Cleanup + if (Test-Path $SERVICE_PID_FILE) { + Remove-Item -Path $SERVICE_PID_FILE -Force -ErrorAction SilentlyContinue + } + } + } +} diff --git a/rootfs/Windows/System32/pkmgr b/rootfs/Windows/System32/pkmgr new file mode 100755 index 0000000..11c9104 --- /dev/null +++ b/rootfs/Windows/System32/pkmgr @@ -0,0 +1,155 @@ +#!/usr/bin/env sh +# shellcheck shell=sh +# shellcheck disable=SC2016 +# - - - - - - - - - - - - - - - - - - - - - - - - - +USER_UID="$(id -u 2>/dev/null || echo 0)" +USER_GID="$(id -g 2>/dev/null || echo 0)" +# - - - - - - - - - - - - - - - - - - - - - - - - - +# Detect package manager +if [ -x "$(command -v winget 2>/dev/null)" ]; then + pkmgr_cmd="winget" + pkmgr_clean_cmd="true" + pkmgr_mkcache_cmd="true" + pkmgr_update_cmd="$pkmgr_cmd upgrade --all --accept-source-agreements --accept-package-agreements" + pkmgr_install_cmd="$pkmgr_cmd install --accept-source-agreements --accept-package-agreements $PKMGR_OPTS" +elif [ -x "$(command -v choco 2>/dev/null)" ]; then + pkmgr_cmd="choco" + pkmgr_clean_cmd="$pkmgr_cmd cache clean" + pkmgr_mkcache_cmd="true" + pkmgr_update_cmd="$pkmgr_cmd upgrade all -y" + pkmgr_install_cmd="$pkmgr_cmd install -y $PKMGR_OPTS" +elif [ -x "$(command -v apt 2>/dev/null)" ]; then + export DEBIAN_FRONTEND=noninteractive + pkmgr_cmd="apt" + pkmgr_clean_cmd="$pkmgr_cmd clean" + pkmgr_mkcache_cmd="$pkmgr_cmd update" + pkmgr_update_cmd="$pkmgr_cmd upgrade -yy" + pkmgr_install_cmd="$pkmgr_cmd install -yy $PKMGR_OPTS" + pkmgr_install_post="$pkmgr_cmd --fix-broken install" +elif [ -x "$(command -v apt-get 2>/dev/null)" ]; then + export DEBIAN_FRONTEND=noninteractive + pkmgr_cmd="apt-get" + pkmgr_clean_cmd="$pkmgr_cmd clean" + pkmgr_mkcache_cmd="$pkmgr_cmd update" + pkmgr_update_cmd="$pkmgr_cmd upgrade -yy" + pkmgr_install_cmd="$pkmgr_cmd install -yy $PKMGR_OPTS" + pkmgr_install_post="$pkmgr_cmd --fix-broken install" +elif [ -x "$(command -v dnf 2>/dev/null)" ]; then + pkmgr_cmd="dnf" + pkmgr_clean_cmd="$pkmgr_cmd clean all" + pkmgr_mkcache_cmd="$pkmgr_cmd makecache" + pkmgr_update_cmd="$pkmgr_cmd update -y --skip-broken $PKMGR_OPTS" + pkmgr_install_cmd="$pkmgr_cmd install -y --skip-broken $PKMGR_OPTS" +elif [ -x "$(command -v yum 2>/dev/null)" ]; then + pkmgr_cmd="yum" + pkmgr_clean_cmd="$pkmgr_cmd clean all" + pkmgr_mkcache_cmd="$pkmgr_cmd makecache" + pkmgr_update_cmd="$pkmgr_cmd update -y --skip-broken $PKMGR_OPTS" + pkmgr_install_cmd="$pkmgr_cmd install -y --skip-broken $PKMGR_OPTS" +elif [ -n "$(command -v pacman 2>/dev/null)" ]; then + pkmgr_cmd="pacman" + pkmgr_mkcache_cmd="true" + pkmgr_clean_cmd="$pkmgr_cmd -Scc --noconfirm" + pkmgr_update_cmd="$pkmgr_cmd -Syyu --noconfirm $PKMGR_OPTS" + pkmgr_install_cmd="$pkmgr_cmd -Syy --noconfirm $PKMGR_OPTS" +elif [ -x "$(command -v apk 2>/dev/null)" ]; then + pkmgr_cmd="apk" + pkmgr_mkcache_cmd="true" + pkmgr_clean_cmd="$pkmgr_cmd cache clean" + pkmgr_update_cmd="$pkmgr_cmd -U upgrade --no-cache $PKMGR_OPTS" + pkmgr_install_cmd="$pkmgr_cmd add --no-cache $PKMGR_OPTS" +elif [ -x "$(command -v zypper 2>/dev/null)" ]; then + pkmgr_cmd="zypper" + pkmgr_mkcache_cmd="true" + pkmgr_clean_cmd="$pkmgr_cmd clean --all" + pkmgr_update_cmd="$pkmgr_cmd update -y $PKMGR_OPTS" + pkmgr_install_cmd="$pkmgr_cmd install -y $PKMGR_OPTS" +else + pkmgr_cmd="true" + pkmgr_mkcache_cmd="$pkmgr_cmd" + pkmgr_clean_cmd="$pkmgr_cmd" + pkmgr_update_cmd="$pkmgr_cmd" + pkmgr_install_cmd="$pkmgr_cmd" +fi +# - - - - - - - - - - - - - - - - - - - - - - - - - +if [ -f "C:/config/pkmgr/settings.conf" ]; then + . "C:/config/pkmgr/settings.conf" +elif [ -f "C:/ProgramData/pkmgr/settings.conf" ]; then + . "C:/ProgramData/pkmgr/settings.conf" +else + mkdir -p "C:/config/pkmgr" + cat <"C:/config/pkmgr/settings.conf" +pkmgr_cmd="$pkmgr_cmd" +pkmgr_clean_cmd="$pkmgr_clean_cmd" +pkmgr_update_cmd="$pkmgr_update_cmd" +pkmgr_install_cmd="$pkmgr_install_cmd" +pkmgr_mkcache_cmd="$pkmgr_mkcache_cmd" +EEOF +fi +# - - - - - - - - - - - - - - - - - - - - - - - - - +[ -n "$pkmgr_cmd" ] || { echo "Can not determine the package manager" && exit 1; } +# - - - - - - - - - - - - - - - - - - - - - - - - - +case "$1" in +pip) + shift 1 + pip_bin="$(command -v python3 2>/dev/null || command -v python2 2>/dev/null || command -v python 2>/dev/null || echo "")" + py_version="$($pip_bin --version | sed 's|[pP]ython ||g' | awk -F '.' '{print $1$2}' | grep '[0-9]' || echo "0")" + [ "$py_version" -gt "310" ] && pip_opts="--break-system-packages " || pip_opts="" + case "$1" in + install) + shift 1 + pkg_list="$*" + for pkg in $pkg_list; do + $pip_bin -m pip $pip_opts "$pkg" + done + ;; + *) + for pkg in "$@"; do + $pip_bin -m pip "$pkg" + done + ;; + esac + exit + ;; +install) + shift 1 + [ -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")" + else + install_list="$*" + fi + for pkg in $install_list;do + echo "installing packages command: $pkmgr_install_cmd $pkg" + $pkmgr_install_cmd $pkg + if [ -n "$pkmgr_install_post" ]; then eval $pkmgr_install_post; fi + done + exit + ;; +update | upgrade) + shift $# + [ "$USER_UID" -eq 0 ] || [ "$USER" = "root" ] || pkmgr_update_cmd="sudo $pkmgr_install_cmd" + echo "Updating packages command: $pkmgr_update_cmd" + $pkmgr_mkcache_cmd + $pkmgr_update_cmd + exit $? + ;; +clean) + shift $# + [ -n "$1" ] || exit 0 + [ "$USER_UID" -eq 0 ] || [ "$USER" = "root" ] || pkmgr_clean_cmd="sudo $pkmgr_clean_cmd" + echo "Cleaning package cache: $pkmgr_clean_cmd" + $pkmgr_clean_cmd + exit $? + ;; +*) + [ -n "$1" ] || exit 0 + [ "$USER_UID" -eq 0 ] || [ "$USER" = "root" ] || pkmgr_cmd="sudo $pkmgr_cmd" + echo "executing packages command: $pkmgr_cmd $*" + $pkmgr_cmd "$@" + exit $? + ;; +esac +# - - - - - - - - - - - - - - - - - - - - - - - - - +# end diff --git a/rootfs/Windows/System32/pkmgr.ps1 b/rootfs/Windows/System32/pkmgr.ps1 new file mode 100644 index 0000000..6c202b4 --- /dev/null +++ b/rootfs/Windows/System32/pkmgr.ps1 @@ -0,0 +1,102 @@ +# PowerShell Package Manager Wrapper +# Supports winget, chocolatey, and can be extended +param( + [Parameter(Mandatory=$false)] + [string]$Action = "", + [Parameter(ValueFromRemainingArguments=$true)] + [string[]]$Packages +) + +$ErrorActionPreference = 'Stop' + +# Detect package manager +$pkgMgr = $null +$installCmd = $null +$updateCmd = $null +$cleanCmd = $null + +if (Get-Command winget -ErrorAction SilentlyContinue) { + $pkgMgr = "winget" + $installCmd = { param($pkg) & winget install --id $pkg --accept-source-agreements --accept-package-agreements --silent } + $updateCmd = { & winget upgrade --all --accept-source-agreements --accept-package-agreements --silent } + $cleanCmd = { Write-Host "Winget cache management" } +} elseif (Get-Command choco -ErrorAction SilentlyContinue) { + $pkgMgr = "chocolatey" + $installCmd = { param($pkg) & choco install $pkg -y } + $updateCmd = { & choco upgrade all -y } + $cleanCmd = { & choco cache clean } +} else { + Write-Error "No package manager found. Please install winget or chocolatey." + exit 1 +} + +Write-Host "Using package manager: $pkgMgr" + +# Load config if exists +$configPath = "C:\config\pkmgr\settings.ps1" +if (Test-Path $configPath) { + . $configPath +} + +# Handle commands +switch ($Action.ToLower()) { + "install" { + if (-not $Packages -or $Packages.Count -eq 0) { + Write-Warning "No packages specified" + exit 0 + } + + foreach ($pkg in $Packages) { + if ($pkg.Trim() -ne "") { + Write-Host "Installing package: $pkg" + try { + & $installCmd $pkg + } catch { + Write-Error "Failed to install $pkg : $_" + } + } + } + } + + "update" { + Write-Host "Updating all packages" + & $updateCmd + } + + "upgrade" { + Write-Host "Upgrading all packages" + & $updateCmd + } + + "clean" { + Write-Host "Cleaning package cache" + & $cleanCmd + + # Clean Windows temp + Remove-Item -Path 'C:\Windows\Temp\*' -Recurse -Force -ErrorAction SilentlyContinue + Remove-Item -Path "C:\Users\$env:USERNAME\AppData\Local\Temp\*" -Recurse -Force -ErrorAction SilentlyContinue + } + + "version" { + if ($pkgMgr -eq "winget") { + & winget --version + } elseif ($pkgMgr -eq "chocolatey") { + & choco --version + } + } + + default { + Write-Host "pkmgr - Package Manager Wrapper for Windows Containers" + Write-Host "" + Write-Host "Usage: pkmgr [packages...]" + Write-Host "" + Write-Host "Actions:" + Write-Host " install - Install package(s)" + Write-Host " update - Update all packages" + Write-Host " upgrade - Upgrade all packages" + Write-Host " clean - Clean package cache" + Write-Host " version - Show package manager version" + Write-Host "" + Write-Host "Current package manager: $pkgMgr" + } +}