{"id":19167093,"url":"https://github.com/powerman/alpine-runit-volume","last_synced_at":"2026-02-21T09:02:28.735Z","repository":{"id":39796967,"uuid":"103006072","full_name":"powerman/alpine-runit-volume","owner":"powerman","description":"Docker base image to run microservice with a data volume","archived":false,"fork":false,"pushed_at":"2025-02-22T07:39:11.000Z","size":86,"stargazers_count":3,"open_issues_count":37,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-10T14:47:28.862Z","etag":null,"topics":["alpine","alpine-image","base-image","docker","docker-image","runit"],"latest_commit_sha":null,"homepage":null,"language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/powerman.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-09-10T05:27:56.000Z","updated_at":"2022-11-07T03:17:45.000Z","dependencies_parsed_at":"2023-02-08T17:31:41.348Z","dependency_job_id":"86a5491e-f3a1-4095-be3d-d84e1288c066","html_url":"https://github.com/powerman/alpine-runit-volume","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/powerman/alpine-runit-volume","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/powerman%2Falpine-runit-volume","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/powerman%2Falpine-runit-volume/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/powerman%2Falpine-runit-volume/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/powerman%2Falpine-runit-volume/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/powerman","download_url":"https://codeload.github.com/powerman/alpine-runit-volume/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/powerman%2Falpine-runit-volume/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29677881,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-21T06:23:40.028Z","status":"ssl_error","status_checked_at":"2026-02-21T06:23:39.222Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["alpine","alpine-image","base-image","docker","docker-image","runit"],"created_at":"2024-11-09T09:35:46.771Z","updated_at":"2026-02-21T09:02:23.728Z","avatar_url":"https://github.com/powerman.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Docker base image to run microservice with a data volume\n\n[![Release](https://img.shields.io/github/v/release/powerman/alpine-runit-volume.svg)](https://github.com/powerman/alpine-runit-volume/releases/latest)\n[![Docker Automated Build](https://img.shields.io/docker/automated/powerman/alpine-runit-volume.svg)](https://hub.docker.com/r/powerman/alpine-runit-volume/tags)\n[![CI](https://github.com/powerman/alpine-runit-volume/workflows/CI/badge.svg?event=push)](https://github.com/powerman/alpine-runit-volume/actions?query=workflow%3ACI%2FCD)\n\n\u003c!-- START doctoc generated TOC please keep comment here to allow auto update --\u003e\n\u003c!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --\u003e\n**Table of Contents**\n\n- [Overview](#overview)\n- [Usage](#usage)\n- [How it works](#how-it-works)\n- [Alternatives](#alternatives)\n\n\u003c!-- END doctoc generated TOC please keep comment here to allow auto update --\u003e\n\n## Overview\n\nThis base docker image is designed to:\n\n- Correctly run microservice with multiple processes:\n  - Clean up zombie processes.\n  - Graceful shutdown on `docker stop`.\n  - Easy to run extra services (syslog, cron, ssh, etc.).\n  - On essential service crash you can either restart it or stop\n    container.\n- Handle persistent storage permissions and migrations:\n  - Microservice can run as non-root account \"app\".\n  - Account \"app\" is the owner of attached data volume directory.\n    - In case of using bind mount this account will have same UID/GID as\n      mounted directory - so you don't get files with unusual ownership in\n      this directory as result of running container.\n    - In case of using new volume it ownership will be changed to random\n      UID/GID (to better isolate container's data and processes). When\n      container will start next time using same volume it'll use same\n      UID/GID.\n- Be small and secure, thanks to Alpine Linux.\n\n## Usage\n\n```Dockerfile\nFROM powerman/alpine-runit-volume:v0.4.0\n\n# [OPTIONAL] Change default directory with volume (/data):\nENV VOLUME_DIR=/home/app/var/data\n\n# [OPTIONAL] Move syslog log dir to default volume dir:\nENV SYSLOG_DIR=$VOLUME_DIR/syslog\n\n# [OPTIONAL] Use anonymous volume if real volume was not provided:\nVOLUME $VOLUME_DIR\n\n# Add your files:\nCOPY . .\n\n# [OPTIONAL] Use cron service and setup /home/app/crontab for user \"app\":\nRUN ln -s /etc/sv/dcron /etc/service/cron; \\\n    install -m 0600 /home/app/crontab /etc/crontabs/app; \\\n    echo app \u003e\u003e /etc/crontabs/cron.update\n\n# Either install your runit services (./init/ directory is just an example):\nRUN ln -nsf \"$PWD\"/init/* /etc/service/\n# or run your microservice as PID1 (without runit):\nCMD [\"my-pid-1-app\"]\n```\n\nThese environment variables can be provided when starting container:\n\n- `APP_UID`, `APP_GID`: numeric UID/GID to be used for \"app\" account and\n  to set ownership for root directory of attached volume.\n  - If `APP_UID=0` then both will be ignored.\n  - I recommend to use values between 1000 and 60000 to avoid conflicts\n    with existing accounts.\n- `VOLUME_DIR`: directory with data volume (`/data` by default)\n- `SYSLOG_DIR`: directory with syslog logs (`/var/log` by default)\n\nTo run your command using \"app\" account: `chpst -u app …` (use in your\nservice's `./run` and `./finish` scripts).\n\nTo gracefully shutdown container on essential service exit/crash add to\nthat service's `./finish` script (run as root): `sv down . /etc/sv/runsvdir`\n\nBy default, your service's STDOUT/STDERR will be sent to docker logs\n(using \"stdout\" log stream for both). To redirect your service's STDOUT to\nsyslog you can pipe output of your service to `logger` tool using this\n`./log/run` script for your service:\n\n```sh\n#!/bin/sh\nsv start syslog \u003e/dev/null 2\u003e\u00261 || exit 1\nexec chpst -u app logger\n```\n\nSyslog service is enabled by default (unless you'll run your app as PID 1)\nand save logs into `SYSLOG_DIR`. You can configure maximum log size and\namount of old rotated log files (10 x 1MB files by default) and other\nfeatures (duplicating selected log records to docker log, sending to\nnetwork syslog by UDP, etc.) using\n[/var/log/config](http://smarden.org/runit/svlogd.8.html#sect6).\n\nIf you enable `/etc/sv/dcron` service you can setup cron tasks using this\n[crontab format](https://github.com/dubiousjim/dcron/blob/master/crontab.markdown).\n\n## How it works\n\nWhen container starts `setup-volume` will be executed as `ENTRYPOINT` to:\n\n- create user account \"app\"\n  - use UID/GID provided in environment variables `APP_UID`/`APP_GID`\n    if `APP_UID` is greater than 0\n  - use UID/GID of current owner of root directory of data volume,\n    if owner's UID is greater than 0\n  - generate random UID/GID between 10000 and 42767 (inclusive)\n  - if `/var/run/docker.sock` exists add user \"app\" to its group\n- ensure root directory of data volume belongs to user \"app\"\n  - use path for data volume provided in environment variable `VOLUME_DIR`\n    or `/data` (if `VOLUME_DIR` is empty)\n- run `CMD`\n\nIf you'll replace `ENTRYPOINT` with your own script make sure it'll finish\nwith `exec setup-volume \"$@\"` if it doesn't use account \"app\" or call\n`setup-volume true` before using account \"app\".\n\n## Alternatives\n\nMain rationale to create this project instead of using existing\nalternatives was to automate permission/ownership management of data\nvolume and provide much simpler implementation to run multiple processes.\n\n- https://github.com/just-containers/s6-overlay\n- https://phusion.github.io/baseimage-docker/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpowerman%2Falpine-runit-volume","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpowerman%2Falpine-runit-volume","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpowerman%2Falpine-runit-volume/lists"}