├── .github └── workflows │ ├── build_image.yml │ └── deploy_image.yml ├── .gitignore ├── Dockerfile ├── Dockerfile-arm64v8 ├── LICENSE ├── Pipfile ├── Pipfile.lock ├── README.md ├── container-files ├── bootstrap │ ├── Pipfile │ ├── app │ │ ├── cli.py │ │ └── mkdocs │ │ │ └── common.py │ ├── main.py │ └── setup.py └── root │ └── .ssh │ └── config └── docker-compose.yaml /.github/workflows/build_image.yml: -------------------------------------------------------------------------------- 1 | name: Build & Test MKDocs 2 | 3 | on: 4 | push: 5 | branches: [issue/*, feature/*] 6 | pull_request: 7 | branches: [master] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v2 15 | - name: Build Docker image 16 | run: | 17 | export RELEASE=$(grep "MKDOCS_VERSION=" Dockerfile | sed 's|^.*=||g' |awk '{print $1}' | sed 's|"||g') 18 | docker build . --file Dockerfile --tag polinux/mkdocs:${RELEASE} 19 | - name: Test image 20 | run: | 21 | export RELEASE=$(grep "MKDOCS_VERSION=" Dockerfile | sed 's|^.*=||g' |awk '{print $1}' | sed 's|"||g') 22 | docker run -d --cap-add NET_ADMIN -p 8000:8000 --name mkdocs polinux/mkdocs:${RELEASE} 23 | sleep 10 24 | curl -sSLi http://127.0.0.1:8000 | grep '200 OK' 25 | # Test custom port 26 | docker run -d --cap-add NET_ADMIN -p 8001:9000 --name custom -e "DEV_ADDR=0.0.0.0:9000" polinux/mkdocs:${RELEASE} 27 | sleep 10 28 | curl -sSLi http://127.0.0.1:8001 | grep '200 OK' 29 | -------------------------------------------------------------------------------- /.github/workflows/deploy_image.yml: -------------------------------------------------------------------------------- 1 | name: Deploy MKDocs 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | 7 | jobs: 8 | 9 | deploy: 10 | 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v2 15 | - name: Deploy image 16 | run: | 17 | export RELEASE=$(grep "MKDOCS_VERSION=" Dockerfile | sed 's|^.*=||g' |awk '{print $1}' | sed 's|"||g') 18 | docker build . --file Dockerfile --tag polinux/mkdocs:${RELEASE} 19 | docker tag polinux/mkdocs:${RELEASE} polinux/mkdocs:latest 20 | docker login -u ${{ secrets.DOCKER_HUB_USER }} -p ${{ secrets.DOCKER_HUB_PASS }} 21 | docker push polinux/mkdocs:${RELEASE} 22 | docker push polinux/mkdocs:latest -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.jenkins 2 | /.vscode 3 | .idea 4 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.18.3 2 | 3 | ENV MKDOCS_VERSION=1.5.2 \ 4 | DOCS_DIRECTORY='/mkdocs' \ 5 | LIVE_RELOAD_SUPPORT='false' \ 6 | ADD_MODULES='false' \ 7 | FAST_MODE='false' \ 8 | PYTHONUNBUFFERED=1 \ 9 | GIT_REPO='false' \ 10 | GIT_BRANCH='master' \ 11 | AUTO_UPDATE='false' \ 12 | UPDATE_INTERVAL=15 13 | 14 | ADD container-files/ / 15 | 16 | RUN \ 17 | apk add --update \ 18 | ca-certificates \ 19 | bash \ 20 | git \ 21 | openssh \ 22 | python3 \ 23 | python3-dev \ 24 | py3-pip \ 25 | build-base && \ 26 | pip install --upgrade pip && \ 27 | pip install mkdocs==${MKDOCS_VERSION} && \ 28 | cd /bootstrap && pip install -e /bootstrap && \ 29 | rm -rf /tmp/* /var/tmp/* /var/cache/apk/* /var/cache/distfiles/* && \ 30 | chmod 600 /root/.ssh/config 31 | 32 | CMD ["/usr/bin/python3", "/bootstrap/main.py", "start"] -------------------------------------------------------------------------------- /Dockerfile-arm64v8: -------------------------------------------------------------------------------- 1 | FROM arm64v8/alpine 2 | 3 | ENV MKDOCS_VERSION=1.5.2 \ 4 | DOCS_DIRECTORY='/mkdocs' \ 5 | LIVE_RELOAD_SUPPORT='false' \ 6 | ADD_MODULES='false' \ 7 | FAST_MODE='false' \ 8 | PYTHONUNBUFFERED=1 \ 9 | GIT_REPO='false' \ 10 | GIT_BRANCH='master' \ 11 | AUTO_UPDATE='false' \ 12 | UPDATE_INTERVAL=15 13 | 14 | ADD container-files/ / 15 | 16 | RUN \ 17 | apk add --update \ 18 | ca-certificates \ 19 | bash \ 20 | git \ 21 | openssh \ 22 | python3 \ 23 | python3-dev \ 24 | py3-pip \ 25 | build-base && \ 26 | pip install --upgrade pip && \ 27 | pip install mkdocs==${MKDOCS_VERSION} && \ 28 | cd /bootstrap && pip install -e /bootstrap && \ 29 | rm -rf /tmp/* /var/tmp/* /var/cache/apk/* /var/cache/distfiles/* && \ 30 | chmod 600 /root/.ssh/config 31 | 32 | CMD ["/usr/bin/python3", "/bootstrap/main.py", "start"] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Przemysław Ożgo 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. 22 | -------------------------------------------------------------------------------- /Pipfile: -------------------------------------------------------------------------------- 1 | [[source]] 2 | name = "pypi" 3 | url = "https://pypi.org/simple" 4 | verify_ssl = true 5 | 6 | [dev-packages] 7 | 8 | [packages] 9 | 10 | [requires] 11 | python_version = "3.11" 12 | -------------------------------------------------------------------------------- /Pipfile.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_meta": { 3 | "hash": { 4 | "sha256": "7f7606f08e0544d8d012ef4d097dabdd6df6843a28793eb6551245d4b2db4242" 5 | }, 6 | "pipfile-spec": 6, 7 | "requires": { 8 | "python_version": "3.8" 9 | }, 10 | "sources": [ 11 | { 12 | "name": "pypi", 13 | "url": "https://pypi.org/simple", 14 | "verify_ssl": true 15 | } 16 | ] 17 | }, 18 | "default": {}, 19 | "develop": {} 20 | } 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### MkDocs in a docker. 2 | 3 | [![Discord](https://img.shields.io/discord/720919856815276063)](https://discord.com/channels/720919856815276063/720920716249137233) 4 | [![Docker Image MKDocs](https://github.com/pozgo/docker-mkdocs/workflows/Docker%20Image%20MKDocs/badge.svg?branch=master)](https://github.com/pozgo/docker-mkdocs/actions?query=workflow%3A%22Build+%26+Test+MKDocs%22) 5 | [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fpozgo%2Fdocker-mkdocs.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fpozgo%2Fdocker-mkdocs?ref=badge_shield) 6 | 7 | [![GitHub Open Issues](https://img.shields.io/github/issues/pozgo/docker-mkdocs.svg)](https://github.com/pozgo/docker-mkdocs/issues) 8 | [![GitHub Stars](https://img.shields.io/github/stars/pozgo/docker-mkdocs.svg)](https://github.com/pozgo/docker-mkdocs) 9 | [![GitHub Forks](https://img.shields.io/github/forks/pozgo/docker-mkdocs.svg)](https://github.com/pozgo/docker-mkdocs) 10 | [![](https://img.shields.io/github/release/pozgo/docker-mkdocs.svg)](http://microbadger.com/images/pozgo/docker-mkdocs) 11 | [![](https://images.microbadger.com/badges/image/polinux/mkdocs.svg)](http://microbadger.com/images/polinux/mkdocs) 12 | 13 | [![Docker build](http://dockeri.co/image/polinux/mkdocs)](https://hub.docker.com/r/polinux/mkdocs/) 14 | 15 | Felling like supporting me in my projects use donate button. Thank You! 16 | [![](https://img.shields.io/badge/donate-PayPal-blue.svg)](https://www.paypal.me/POzgo) 17 | 18 | [Docker Image](https://registry.hub.docker.com/u/polinux/mkdocs/) with [MkDocs](http://www.mkdocs.org/). It's using tiny image provided by Alpine. 19 | MkDocs is a fast, simple and downright gorgeous static site generator that's geared towards building project documentation. Documentation source files are written in Markdown, and configured with a single YAML configuration file. 20 | 21 | Purpose of this image was to simplify the process of deploying MkDocs. This image is based on Alpine Linux to minimize the size of the image. 22 | 23 | ### ARM based image 24 | 25 | Example build: 26 | 27 | ```bash 28 | docker buildx build --platform linux/arm64 --file Dockerfile-arm64v8 -t polinux/mkdocs:arm64v8-1.2.2 . 29 | ``` 30 | 31 | ### Docker compose example 32 | 33 | ```yaml 34 | version: '3' 35 | 36 | services: 37 | mkdocs: 38 | container_name: mkdocs 39 | image: polinux/mkdocs:1.2.2 40 | restart: always 41 | ports: 42 | - "8000:8000" 43 | environment: 44 | LIVE_RELOAD_SUPPORT: 'true' 45 | ADD_MODULES: 'fontawesome-markdown mkdocs-git-revision-date-localized-plugin mkdocs-material' 46 | FAST_MODE: 'true' 47 | DOCS_DIRECTORY: '/mkdocs' 48 | GIT_REPO: 'git@github.com:username/docs.git' 49 | UPDATE_INTERVAL: 15 50 | AUTO_UPDATE: 'true' 51 | volumes: 52 | - $HOME/.ssh/id_rsa:/root/.ssh/id_rsa 53 | ``` 54 | 55 | ### Environmental Variables 56 | 57 | |Variable|Notes|Default| 58 | |:--|:--|---| 59 | |`LIVE_RELOAD_SUPPORT`|Support for live reload feature. |`false`| 60 | |`ADD_MODULES`|List of module to install.|`false`| 61 | |`FAST_MODE`|Enable fast mode. Rebuilds only changed/added files|`false`| 62 | |`DOCS_DIRECTORY`|Directory in which documentation is mounted inside of container|`/mkdocs`| 63 | |`GIT_REPO`|Repository address. Will require ssh key for ssh connection. Example: `-v ${HOME}/.ssh/id_rsa:/root/.ssh/id_rsa`|`false`| 64 | |`GIT_BRANCH`|Self explanatory|`master`| 65 | |`AUTO_UPDATE`|Auto update for git repository support|`false`| 66 | |`UPDATE_INTERVAL`|Update interval in *minutes* - used only when `AUTO_UPDATE` set to `true`|every `15` minutes| 67 | |`DEV_ADDR`|Custom IP address and port to serve documentation locall|`0.0.0.0:8000`| 68 | 69 | ### Usage 70 | 71 | ```bash 72 | docker run \ 73 | -ti \ 74 | --name mkdocs \ 75 | polinux/mkdocs 76 | ``` 77 | 78 | Custom config with `git` repository as source of documentation 79 | ```bash 80 | docker run \ 81 | -ti \ 82 | --name mkdocs \ 83 | -p 80:9000 \ 84 | -e "ADD_MODULES=mkdocs-bootstrap mkdocs-gitbook mkdocs-bootstrap4" \ 85 | -e "LIVE_RELOAD_SUPPORT=true" \ 86 | -e "FAST_MODE=true" \ 87 | -e "DOCS_DIRECTORY=/my_docs" \ 88 | -e "GIT_REPO=https://my_repos/custom-docs.git" \ 89 | -e "GIT_BRANCH=develop" \ 90 | -e "AUTO_UPDATE=true" \ 91 | -e "UPDATE_INTERVAL=1" \ 92 | -e "DEV_ADDR=0.0.0.0:9000" \ 93 | -v ${HOME}/.ssh/id_rsa:/root/.ssh/id_rsa \ 94 | polinux/mkdocs 95 | ``` 96 | 97 | See `docker-compose.yaml` for all compose options examples 98 | 99 | ### Update git repo based deployment 100 | Assuming you are using git repository as source of documentation there are two options available for updating the content of the docs. 101 | 102 | #### Manual 103 | 104 | Assuming that container name is `mkdocs` 105 | ```bash 106 | docker exec -ti mkdocs bootstrap update 107 | Pulled branch: master 108 | Commit: a4000c525f6db977777bf758987c4df0b44f59b4 109 | Commit Message: Updated nodejs 110 | Date: 2020-03-24 18:52:43 111 | Author: Przemek Ozgo 112 | ``` 113 | 114 | #### AUTO_UPDATE 115 | there are two environmental variables that can be used for AUTO UPDATE. 116 | See table above ^^ 117 | 118 | 119 | ### Build 120 | 121 | ```bash 122 | docker build -t polinux/mkdocs . 123 | ``` 124 | 125 | Docker troubleshooting 126 | ====================== 127 | 128 | Use docker command to see if all required containers are up and running: 129 | 130 | ```bash 131 | docker ps 132 | ``` 133 | 134 | Check logs of mkdocs server container: 135 | 136 | ```bash 137 | docker logs mkdocs 138 | ``` 139 | 140 | Sometimes you might just want to review how things are deployed inside a running 141 | container, you can do this by executing a _bash shell_ through _docker's 142 | exec_ command: 143 | 144 | ```bash 145 | docker exec -ti mkdocs /bin/bash 146 | ``` 147 | 148 | History of an image and size of layers: 149 | 150 | ```bash 151 | docker history --no-trunc=true polinux/mkdocs | tr -s ' ' | tail -n+2 | awk -F " ago " '{print $2}' 152 | ``` 153 | 154 | ## Author 155 | 156 | Przemyslaw Ozgo 157 | -------------------------------------------------------------------------------- /container-files/bootstrap/Pipfile: -------------------------------------------------------------------------------- 1 | [[source]] 2 | name = "pypi" 3 | url = "https://pypi.org/simple" 4 | verify_ssl = true 5 | 6 | [dev-packages] 7 | 8 | [packages] 9 | click = "*" 10 | 11 | [requires] 12 | python_version = "3.8" 13 | -------------------------------------------------------------------------------- /container-files/bootstrap/app/cli.py: -------------------------------------------------------------------------------- 1 | import click 2 | from app.mkdocs import common 3 | 4 | """CLI commands interface 5 | 6 | These are the primitive operation wrappers that the CLI 7 | will expose and be available to invoke. 8 | In order to do so, the comprehensive Click library is used to 9 | create commands, subcommands, parameters, flags... 10 | 11 | .. _Click CLI library docs: 12 | https://click.palletsprojects.com/en/7.x/#documentation 13 | """ 14 | 15 | 16 | @click.group(chain=True) 17 | def cli() -> None: 18 | """ 19 | Bootstrap CLI 20 | """ 21 | 22 | 23 | @cli.command('start', help='Start Application') 24 | def start(): 25 | common.start() 26 | 27 | 28 | @cli.command('update', help='Update documentation code from repository') 29 | def update(): 30 | common.update_repo() 31 | -------------------------------------------------------------------------------- /container-files/bootstrap/app/mkdocs/common.py: -------------------------------------------------------------------------------- 1 | import os 2 | from termcolor import colored 3 | import git 4 | from datetime import datetime 5 | from crontab import CronTab 6 | 7 | docks_dir = os.environ['DOCS_DIRECTORY'] 8 | modules = os.environ['ADD_MODULES'] 9 | repo = os.environ['GIT_REPO'] 10 | git_branch = os.environ['GIT_BRANCH'] 11 | auto_update = os.environ['AUTO_UPDATE'] 12 | interval = int(os.environ['UPDATE_INTERVAL']) 13 | 14 | 15 | def start(): 16 | """ 17 | Start mkdocs server 18 | :return: 19 | """ 20 | if modules != 'false': 21 | _install_modules(modules) 22 | if repo != 'false': 23 | _clone_repo(repo) 24 | _check_previous_installation() 25 | print('Starting MKDocs') 26 | os.chdir(docks_dir) 27 | if "DEV_ADDR" in os.environ: 28 | _dev_addr = os.environ['DEV_ADDR'] 29 | else: 30 | _dev_addr = '0.0.0.0:8000' 31 | os.system(f'mkdocs serve -a {_dev_addr} {_live_reload()} {_fast_mode()}') 32 | 33 | 34 | def _install_modules(modules): 35 | """ 36 | Install Additional Modules 37 | :param modules: str - List of modules to install 38 | :return: 39 | """ 40 | print(colored(f'Installing python modules: {modules}', 'green')) 41 | os.system(f'pip install -q {modules}') 42 | print(colored(f'Modules installed.', 'green')) 43 | 44 | 45 | def _check_previous_installation(): 46 | """ 47 | Check if previous installation present 48 | Creates empty documentation if none detected 49 | :return: 50 | """ 51 | if not os.path.exists(docks_dir + '/mkdocs.yml'): 52 | print(colored( 53 | f'No documentation found in ({docks_dir}). Creating new one.', 'yellow')) 54 | if not os.path.exists(docks_dir): 55 | os.mkdir(docks_dir) 56 | print(colored(f'Starting fresh installation', 'green')) 57 | os.system(f'mkdocs new {docks_dir}/') 58 | else: 59 | print( 60 | colored(f'Detected previous installation in ({docks_dir}).', 'green')) 61 | 62 | 63 | def _live_reload(): 64 | """ 65 | Live Reload 66 | Auto Reload on file change 67 | :return: 68 | """ 69 | if os.environ['LIVE_RELOAD_SUPPORT'] == 'false': 70 | print(colored(f'LIVE RELOAD - [ DISABLED ]', 'red')) 71 | reload = '--no-livereload' 72 | else: 73 | print(colored(f'LIVE RELOAD - [ ENABLED ]', 'green')) 74 | reload = '' 75 | return reload 76 | 77 | 78 | def _fast_mode(): 79 | """ 80 | Fast Mode 81 | Enables/Disables fast reload. 82 | Enabled: build only files that got changed 83 | Disabled: builds all files regardless of changes 84 | :return: 85 | """ 86 | if os.environ['FAST_MODE'] == 'false': 87 | print(colored(f'FAST_MODE - [ DISABLED ]', 'red')) 88 | fast = '' 89 | else: 90 | print(colored(f'FAST_MODE - [ ENABLED ]', 'green')) 91 | fast = '--dirtyreload' 92 | return fast 93 | 94 | 95 | def _set_auto_update(interval): 96 | """ 97 | Creates cron job for auto updating repository 98 | :param interval: (every x minutes) 99 | :return: 100 | """ 101 | os.system(f'crond') 102 | cron = CronTab(user='root') 103 | cron.remove_all() 104 | job = cron.new(command='bootstrap update', comment='update') 105 | job.minute.every(interval) 106 | cron.write() 107 | 108 | 109 | def _clone_repo(repo): 110 | """ 111 | Clone Documentation Code from git repository 112 | :return: 113 | """ 114 | if not os.path.exists(docks_dir + '/mkdocs.yml'): 115 | print(colored(f'Getting documentation from: {repo}', 'green')) 116 | git.Repo.clone_from(repo, docks_dir, branch=git_branch) 117 | 118 | if auto_update == 'true': 119 | print(colored(f'AUTO_UPDATE - [ ENABLED ]', 'green')) 120 | print( 121 | colored(f'UPDATE_INTERVAL set to every {interval} minute/s', 'green')) 122 | _set_auto_update(interval) 123 | 124 | 125 | def update_repo(): 126 | """ 127 | Fetching latest changes 128 | :return: 129 | """ 130 | repo = git.Repo(docks_dir) 131 | for remote in repo.remotes: 132 | remote.fetch() 133 | remote.pull() 134 | headcommit = repo.head.commit 135 | commit_date = datetime.fromtimestamp(headcommit.authored_date) 136 | print(colored( 137 | f'Pulled branch: {git_branch} \nCommit: {headcommit.hexsha} \nCommit Message: {headcommit.message}Date: {commit_date} \nAuthor: {headcommit.committer.name}', 138 | 'green')) 139 | -------------------------------------------------------------------------------- /container-files/bootstrap/main.py: -------------------------------------------------------------------------------- 1 | from app.cli import cli 2 | 3 | if __name__ == '__main__': 4 | cli() 5 | -------------------------------------------------------------------------------- /container-files/bootstrap/setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | setup( 4 | name='bootstrap', 5 | version='1.0.0', 6 | py_modules=['bootstrap'], 7 | include_package_data=True, 8 | install_requires=[ 9 | 'click', 'termcolor', 'GitPython', 'python-crontab' 10 | ], 11 | entry_points=''' 12 | [console_scripts] 13 | bootstrap=app.cli:cli 14 | ''', 15 | ) 16 | -------------------------------------------------------------------------------- /container-files/root/.ssh/config: -------------------------------------------------------------------------------- 1 | Host * 2 | StrictHostKeyChecking no -------------------------------------------------------------------------------- /docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | mkdocs: 5 | container_name: mkdocs 6 | image: polinux/mkdocs:1.5.2 7 | restart: always 8 | ports: 9 | - "8000:8000" 10 | environment: 11 | LIVE_RELOAD_SUPPORT: 'true' 12 | ADD_MODULES: 'fontawesome-markdown mkdocs-git-revision-date-localized-plugin mkdocs-material' 13 | FAST_MODE: 'true' 14 | DOCS_DIRECTORY: '/mkdocs' 15 | GIT_REPO: 'git@github.com:username/docs.git' 16 | UPDATE_INTERVAL: 15 17 | AUTO_UPDATE: 'true' 18 | volumes: 19 | - $HOME/.ssh/id_rsa:/root/.ssh/id_rsa --------------------------------------------------------------------------------