├── .dockerignore ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── docker-compose.yml └── docker ├── Dockerfile ├── entrypoint.sh ├── hooks └── build └── supervisord.conf /.dockerignore: -------------------------------------------------------------------------------- 1 | .env -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .env -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 "CARDONNE Thomas" 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | APP_NAME="tcardonne/github-runner" 2 | 3 | # HELP 4 | # This will output the help for each task 5 | # thanks to https://marmelab.com/blog/2016/02/29/auto-documented-makefile.html 6 | .PHONY: help 7 | help: ## This help. 8 | @awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST) 9 | 10 | .DEFAULT_GOAL := help 11 | 12 | build: ## Build the image 13 | docker build -t $(APP_NAME) docker 14 | 15 | shell: ## Creates a shell inside the container for debug purposes 16 | docker run -it $(APP_NAME) bash 17 | 18 | shell-compose: ## Creates a shell inside the docker-compose service for debug purposes 19 | docker-compose run --rm runner bash 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GitHub Runner - DEPRECATED 2 | 3 | **This repository is deprecated and unmaintained.** 4 | 5 | Consider using: 6 | - [myoung34/docker-github-actions-runner](https://github.com/myoung34/docker-github-actions-runner) 7 | - [actions/actions-runner-controller](https://github.com/actions/actions-runner-controller) 8 | 9 | ----------- 10 | 11 | [![Docker Pulls](https://img.shields.io/docker/pulls/tcardonne/github-runner)](https://hub.docker.com/r/tcardonne/github-runner) 12 | 13 | ----------- 14 | GitHub allows developers to run GitHub Actions workflows on your own runners. 15 | This Docker image allows you to create your own runners on Docker. 16 | 17 | For now, there are only Debian Buster (tagged with `latest` and `vX.Y.Z`) and Ubuntu Focal (tagged with `ubuntu-20.04` and `vX.Y.Z-ubuntu-20.04`) images, but I may add more variants in the future. Feel free to create an issue if you want another base image. 18 | 19 | ## Important notes 20 | 21 | * GitHub [recommends](https://help.github.com/en/github/automating-your-workflow-with-github-actions/about-self-hosted-runners#self-hosted-runner-security-with-public-repositories) that you do **NOT** use self-hosted runners with public repositories, for security reasons. 22 | * Organization level self-hosted runners are supported (see environment variables), but be advised that the GitHub API for organization level runners is still in public beta and subject to changes. 23 | 24 | ## Usage 25 | 26 | ### Basic usage 27 | Use the following command to start listening for jobs: 28 | ```shell 29 | docker run -it --name my-runner \ 30 | -e RUNNER_NAME=my-runner \ 31 | -e GITHUB_ACCESS_TOKEN=token \ 32 | -e RUNNER_REPOSITORY_URL=https://github.com/... \ 33 | tcardonne/github-runner 34 | ``` 35 | 36 | ### Using Docker inside your Actions 37 | 38 | If you want to use Docker inside your runner (ie, build images in a workflow), you can enable Docker siblings by binding the host Docker daemon socket. Please keep in mind that doing this gives your actions full control on the Docker daemon. 39 | 40 | ```shell 41 | docker run -it --name my-runner \ 42 | -e RUNNER_NAME=my-runner \ 43 | -e GITHUB_ACCESS_TOKEN=token \ 44 | -e RUNNER_REPOSITORY_URL=https://github.com/... \ 45 | -v /var/run/docker.sock:/var/run/docker.sock \ 46 | tcardonne/github-runner 47 | ``` 48 | 49 | ### Using docker-compose.yml 50 | 51 | In `docker-compose.yml` : 52 | ```yaml 53 | version: "3.7" 54 | 55 | services: 56 | runner: 57 | image: tcardonne/github-runner:latest 58 | environment: 59 | RUNNER_NAME: "my-runner" 60 | RUNNER_REPOSITORY_URL: ${RUNNER_REPOSITORY_URL} 61 | #RUNNER_ORGANIZATION_URL: ${RUNNER_ORGANIZATION_URL} 62 | GITHUB_ACCESS_TOKEN: ${GITHUB_ACCESS_TOKEN} 63 | volumes: 64 | - /var/run/docker.sock:/var/run/docker.sock 65 | ``` 66 | 67 | You can create a `.env` to provide environment variables when using docker-compose : 68 | ``` 69 | RUNNER_REPOSITORY_URL=https://github.com/your_url/your_repo 70 | # or RUNNER_ORGANIZATION_URL=https://github.com/your-organization 71 | GITHUB_ACCESS_TOKEN=the_runner_token 72 | ``` 73 | 74 | ## Environment variables 75 | 76 | The following environment variables allows you to control the configuration parameters. 77 | 78 | | Name | Description | Required/Default value | 79 | |------|---------------|-------------| 80 | | RUNNER_REPOSITORY_URL | The runner will be linked to this repository URL | Required if `RUNNER_ORGANIZATION_URL` is not provided | 81 | | RUNNER_ORGANIZATION_URL | The runner will be linked to this organization URL. *(Self-hosted runners API for organizations is currently in public beta and subject to changes)* | Required if `RUNNER_REPOSITORY_URL` is not provided | 82 | | GITHUB_ACCESS_TOKEN | Personal Access Token. Used to dynamically fetch a new runner token (recommended, see below). | Required if `RUNNER_TOKEN` is not provided. 83 | | RUNNER_TOKEN | Runner token provided by GitHub in the Actions page. These tokens are valid for a short period. | Required if `GITHUB_ACCESS_TOKEN` is not provided 84 | | RUNNER_WORK_DIRECTORY | Runner's work directory | `"_work"` 85 | | RUNNER_NAME | Name of the runner displayed in the GitHub UI | Hostname of the container 86 | | RUNNER_LABELS | Extra labels in addition to the default: 'self-hosted,Linux,X64' (based on your OS and architecture) | `""` 87 | | RUNNER_REPLACE_EXISTING | `"true"` will replace existing runner with the same name, `"false"` will use a random name if there is conflict | `"true"` 88 | 89 | ## Runner Token 90 | 91 | In order to link your runner to your repository/organization, you need to provide a token. There is two way of passing the token : 92 | 93 | * via `GITHUB_ACCESS_TOKEN` (recommended), containing a [Personnal Access Token](https://github.com/settings/tokens). This token will be used to dynamically fetch a new runner token, as runner tokens are valid for a short period of time. 94 | * For a single-repository runner, your PAT should have `repo` scopes. 95 | * For an organization runner, your PAT should have `admin:org` scopes. 96 | * via `RUNNER_TOKEN`. This token is displayed in the Actions settings page of your organization/repository, when opening the "Add Runner" page. 97 | 98 | ## Runner auto-update behavior 99 | 100 | The GitHub runner (the binary) will update itself when receiving a job, if a new release is available. 101 | In order to allow the runner to exit and restart by itself, the binary is started by a supervisord process. 102 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.7" 2 | 3 | services: 4 | runner: 5 | image: tcardonne/github-runner:latest 6 | environment: 7 | RUNNER_NAME: "my-runner" 8 | RUNNER_REPOSITORY_URL: ${RUNNER_REPOSITORY_URL} 9 | #RUNNER_ORGANIZATION_URL: ${RUNNER_ORGANIZATION_URL} 10 | GITHUB_ACCESS_TOKEN: ${GITHUB_ACCESS_TOKEN} 11 | volumes: 12 | - /var/run/docker.sock:/var/run/docker.sock -------------------------------------------------------------------------------- /docker/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG FROM=debian:buster-slim 2 | FROM ${FROM} 3 | 4 | ARG DEBIAN_FRONTEND=noninteractive 5 | ARG GIT_VERSION="2.26.2" 6 | ARG GH_RUNNER_VERSION 7 | ARG DOCKER_COMPOSE_VERSION="1.27.4" 8 | 9 | ENV RUNNER_NAME="" 10 | ENV RUNNER_WORK_DIRECTORY="_work" 11 | ENV RUNNER_TOKEN="" 12 | ENV RUNNER_REPOSITORY_URL="" 13 | ENV RUNNER_LABELS="" 14 | ENV RUNNER_ALLOW_RUNASROOT=true 15 | ENV GITHUB_ACCESS_TOKEN="" 16 | ENV AGENT_TOOLSDIRECTORY=/opt/hostedtoolcache 17 | 18 | # Labels. 19 | LABEL maintainer="me@tcardonne.fr" \ 20 | org.label-schema.schema-version="1.0" \ 21 | org.label-schema.build-date=$BUILD_DATE \ 22 | org.label-schema.vcs-ref=$VCS_REF \ 23 | org.label-schema.name="tcardonne/github-runner" \ 24 | org.label-schema.description="Dockerized GitHub Actions runner." \ 25 | org.label-schema.url="https://github.com/tcardonne/docker-github-runner" \ 26 | org.label-schema.vcs-url="https://github.com/tcardonne/docker-github-runner" \ 27 | org.label-schema.vendor="Thomas Cardonne" \ 28 | org.label-schema.docker.cmd="docker run -it tcardonne/github-runner:latest" 29 | 30 | RUN DEBIAN_FRONTEND=noninteractive apt-get update && \ 31 | apt-get install -y \ 32 | curl \ 33 | unzip \ 34 | apt-transport-https \ 35 | ca-certificates \ 36 | software-properties-common \ 37 | sudo \ 38 | supervisor \ 39 | jq \ 40 | iputils-ping \ 41 | build-essential \ 42 | zlib1g-dev \ 43 | gettext \ 44 | liblttng-ust0 \ 45 | libcurl4-openssl-dev \ 46 | openssh-client && \ 47 | rm -rf /var/lib/apt/lists/* && \ 48 | apt-get clean 49 | 50 | COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf 51 | RUN chmod 644 /etc/supervisor/conf.d/supervisord.conf 52 | 53 | # Install Docker CLI 54 | RUN curl -fsSL https://get.docker.com -o- | sh && \ 55 | rm -rf /var/lib/apt/lists/* && \ 56 | apt-get clean 57 | 58 | # Install Docker-Compose 59 | RUN curl -L -o /usr/local/bin/docker-compose \ 60 | "https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-$(uname -s)-$(uname -m)" && \ 61 | chmod +x /usr/local/bin/docker-compose 62 | 63 | RUN cd /tmp && \ 64 | curl -sL -o git.tgz \ 65 | https://www.kernel.org/pub/software/scm/git/git-${GIT_VERSION}.tar.gz && \ 66 | tar zxf git.tgz && \ 67 | cd git-${GIT_VERSION} && \ 68 | ./configure --prefix=/usr && \ 69 | make && \ 70 | make install && \ 71 | rm -rf /tmp/* 72 | 73 | RUN mkdir -p /home/runner ${AGENT_TOOLSDIRECTORY} 74 | 75 | WORKDIR /home/runner 76 | 77 | RUN GH_RUNNER_VERSION=${GH_RUNNER_VERSION:-$(curl --silent "https://api.github.com/repos/actions/runner/releases/latest" | grep tag_name | sed -E 's/.*"v([^"]+)".*/\1/')} \ 78 | && curl -L -O https://github.com/actions/runner/releases/download/v${GH_RUNNER_VERSION}/actions-runner-linux-x64-${GH_RUNNER_VERSION}.tar.gz \ 79 | && tar -zxf actions-runner-linux-x64-${GH_RUNNER_VERSION}.tar.gz \ 80 | && rm -f actions-runner-linux-x64-${GH_RUNNER_VERSION}.tar.gz \ 81 | && ./bin/installdependencies.sh \ 82 | && chown -R root: /home/runner \ 83 | && rm -rf /var/lib/apt/lists/* \ 84 | && apt-get clean 85 | 86 | COPY entrypoint.sh /entrypoint.sh 87 | RUN chmod +x /entrypoint.sh 88 | ENTRYPOINT ["/entrypoint.sh"] 89 | CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"] 90 | -------------------------------------------------------------------------------- /docker/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [[ "$@" == "bash" ]]; then 4 | exec $@ 5 | fi 6 | 7 | if [[ -z $RUNNER_NAME ]]; then 8 | echo "RUNNER_NAME environment variable is not set, using '${HOSTNAME}'." 9 | export RUNNER_NAME=${HOSTNAME} 10 | fi 11 | 12 | if [[ -z $RUNNER_WORK_DIRECTORY ]]; then 13 | echo "RUNNER_WORK_DIRECTORY environment variable is not set, using '_work'." 14 | export RUNNER_WORK_DIRECTORY="_work" 15 | fi 16 | 17 | if [[ -z $RUNNER_TOKEN && -z $GITHUB_ACCESS_TOKEN ]]; then 18 | echo "Error : You need to set RUNNER_TOKEN (or GITHUB_ACCESS_TOKEN) environment variable." 19 | exit 1 20 | fi 21 | 22 | if [[ -z $RUNNER_REPOSITORY_URL && -z $RUNNER_ORGANIZATION_URL ]]; then 23 | echo "Error : You need to set the RUNNER_REPOSITORY_URL (or RUNNER_ORGANIZATION_URL) environment variable." 24 | exit 1 25 | fi 26 | 27 | if [[ -z $RUNNER_REPLACE_EXISTING ]]; then 28 | export RUNNER_REPLACE_EXISTING="true" 29 | fi 30 | 31 | CONFIG_OPTS="" 32 | if [ "$(echo $RUNNER_REPLACE_EXISTING | tr '[:upper:]' '[:lower:]')" == "true" ]; then 33 | CONFIG_OPTS="--replace" 34 | fi 35 | 36 | if [[ -n $RUNNER_LABELS ]]; then 37 | CONFIG_OPTS="${CONFIG_OPTS} --labels ${RUNNER_LABELS}" 38 | fi 39 | 40 | if [[ -f ".runner" ]]; then 41 | echo "Runner already configured. Skipping config." 42 | else 43 | if [[ ! -z $RUNNER_ORGANIZATION_URL ]]; then 44 | SCOPE="orgs" 45 | RUNNER_URL="${RUNNER_ORGANIZATION_URL}" 46 | else 47 | SCOPE="repos" 48 | RUNNER_URL="${RUNNER_REPOSITORY_URL}" 49 | fi 50 | 51 | if [[ -n $GITHUB_ACCESS_TOKEN ]]; then 52 | 53 | echo "Exchanging the GitHub Access Token with a Runner Token (scope: ${SCOPE})..." 54 | 55 | _PROTO="$(echo "${RUNNER_URL}" | grep :// | sed -e's,^\(.*://\).*,\1,g')" 56 | _URL="$(echo "${RUNNER_URL/${_PROTO}/}")" 57 | _PATH="$(echo "${_URL}" | grep / | cut -d/ -f2-)" 58 | 59 | RUNNER_TOKEN="$(curl -XPOST -fsSL \ 60 | -H "Authorization: token ${GITHUB_ACCESS_TOKEN}" \ 61 | -H "Accept: application/vnd.github.v3+json" \ 62 | "https://api.github.com/${SCOPE}/${_PATH}/actions/runners/registration-token" \ 63 | | jq -r '.token')" 64 | fi 65 | 66 | ./config.sh \ 67 | --url $RUNNER_URL \ 68 | --token $RUNNER_TOKEN \ 69 | --name $RUNNER_NAME \ 70 | --work $RUNNER_WORK_DIRECTORY \ 71 | $CONFIG_OPTS \ 72 | --unattended 73 | fi 74 | 75 | exec "$@" -------------------------------------------------------------------------------- /docker/hooks/build: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | set -ex 3 | 4 | # This overrides Docker Hub's build command in order to specify the base image 5 | # as build argument. For more information on build hooks and environment 6 | # variables, see: https://docs.docker.com/docker-hub/builds/advanced/ 7 | 8 | # DOCKER_TAG can be : latest, ubuntu-20.04, v1.0.0, v1.0.0-ubuntu-20.04 9 | 10 | if [[ $DOCKER_TAG =~ ^(latest|v[0-9]+\.[0-9]+\.[0-9]+)$ ]]; then 11 | TAG=debian-buster-slim 12 | else 13 | # Remove vX.X.X- suffix 14 | TAG=$(echo $DOCKER_TAG | sed 's/v[0-9]\+.[0-9]\+.[0-9]\+-//') 15 | fi 16 | 17 | # Replace first '-' by ':' 18 | # ie, ubuntu-20.04 will be ubuntu:20.04 (image name) 19 | FROM=${TAG/-/:} 20 | 21 | docker build . \ 22 | --build-arg FROM=$FROM \ 23 | -f ${DOCKERFILE_PATH:-Dockerfile} \ 24 | -t $IMAGE_NAME 25 | -------------------------------------------------------------------------------- /docker/supervisord.conf: -------------------------------------------------------------------------------- 1 | [supervisord] 2 | user=root 3 | nodaemon=true 4 | logfile=/dev/fd/1 5 | logfile_maxbytes=0 6 | loglevel=error 7 | 8 | [program:runner] 9 | directory=/home/runner 10 | command=/home/runner/bin/runsvc.sh 11 | stdout_logfile=/dev/fd/1 12 | stdout_logfile_maxbytes=0 13 | redirect_stderr=true --------------------------------------------------------------------------------