├── .gitignore ├── renovate.json ├── tests ├── test-haskell.sh ├── test-rust.sh ├── test-python.sh ├── test-java.sh ├── test-ruby.sh └── test-latex.sh ├── extras ├── install-ab.sh ├── install-node.sh ├── install-clang.sh ├── install-chrome.sh └── install-postgres.sh ├── .github └── workflows │ ├── reuse.yml │ ├── typos.yml │ ├── xcop.yml │ ├── pdd.yml │ ├── yamllint.yml │ ├── checkmake.yml │ ├── shellcheck.yml │ ├── make.yml │ ├── markdown-lint.yml │ ├── bashate.yml │ ├── actionlint.yml │ ├── hadolint.yml │ └── copyrights.yml ├── rust └── Dockerfile ├── latex ├── update-depends.sh └── Dockerfile ├── REUSE.toml ├── haskell └── Dockerfile ├── LICENSE.txt ├── LICENSES └── MIT.txt ├── README.md ├── python └── Dockerfile ├── java └── Dockerfile ├── ruby └── Dockerfile └── Makefile /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .idea/ 3 | node_modules/ 4 | target/ 5 | .claude/ 6 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "config:recommended" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /tests/test-haskell.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # SPDX-FileCopyrightText: Copyright (c) 2012-2025 Yegor Bugayenko 4 | # SPDX-License-Identifier: MIT 5 | 6 | set -ex -o pipefail 7 | 8 | ghc --version 9 | cabal --version 10 | -------------------------------------------------------------------------------- /tests/test-rust.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # SPDX-FileCopyrightText: Copyright (c) 2012-2025 Yegor Bugayenko 4 | # SPDX-License-Identifier: MIT 5 | 6 | set -ex -o pipefail 7 | 8 | rustc --version 9 | rustfmt --version 10 | cargo --version 11 | -------------------------------------------------------------------------------- /extras/install-ab.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # SPDX-FileCopyrightText: Copyright (c) 2012-2025 Yegor Bugayenko 4 | # SPDX-License-Identifier: MIT 5 | 6 | set -ex -o pipefail 7 | 8 | apt-get update --yes --fix-missing 9 | apt-get install apache2-utils 10 | apt-get clean 11 | 12 | ab -V 13 | -------------------------------------------------------------------------------- /extras/install-node.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # SPDX-FileCopyrightText: Copyright (c) 2012-2025 Yegor Bugayenko 4 | # SPDX-License-Identifier: MIT 5 | 6 | set -ex -o pipefail 7 | 8 | curl -fsSL https://deb.nodesource.com/setup_18.x | bash 9 | apt-get install --yes nodejs 10 | 11 | node --version 12 | npm --version 13 | -------------------------------------------------------------------------------- /tests/test-python.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # SPDX-FileCopyrightText: Copyright (c) 2012-2025 Yegor Bugayenko 4 | # SPDX-License-Identifier: MIT 5 | 6 | set -ex -o pipefail 7 | 8 | python --version 9 | pip --version 10 | 11 | python3 --version 12 | pip3 --version 13 | 14 | pip3 install flake8 15 | flake8 --version 16 | -------------------------------------------------------------------------------- /extras/install-clang.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # SPDX-FileCopyrightText: Copyright (c) 2012-2025 Yegor Bugayenko 4 | # SPDX-License-Identifier: MIT 5 | 6 | set -ex -o pipefail 7 | 8 | wget -qO- https://apt.llvm.org/llvm.sh | bash -s -- 19 9 | 10 | if [ -e /usr/bin/clang ]; then 11 | rm -f /usr/bin/clang 12 | fi 13 | ln -s "$(which clang-19)" /usr/bin/clang 14 | 15 | clang --version 16 | -------------------------------------------------------------------------------- /tests/test-java.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # SPDX-FileCopyrightText: Copyright (c) 2012-2025 Yegor Bugayenko 4 | # SPDX-License-Identifier: MIT 5 | 6 | set -ex -o pipefail 7 | 8 | javac --version 9 | mvn --version 10 | env 11 | gradle --version 12 | 13 | mvn dependency:get -Dartifact=junit:junit:4.11 14 | 15 | [[ "$(javac --version)" =~ 17\.0 ]] 16 | 17 | [[ "$(mvn --version)" =~ 3\.9 ]] 18 | 19 | [ -e /usr/bin/install-postgres.sh ] 20 | -------------------------------------------------------------------------------- /tests/test-ruby.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # SPDX-FileCopyrightText: Copyright (c) 2012-2025 Yegor Bugayenko 4 | # SPDX-License-Identifier: MIT 5 | 6 | set -ex -o pipefail 7 | 8 | ruby --version 9 | xcop --version 10 | pdd --version 11 | curl --version 12 | wget --version 13 | zip -h | head -1 14 | unzip -h | head -1 15 | ssh -V 16 | git --version 17 | docker --version 18 | docker buildx version 19 | 20 | gem install nokogiri 21 | 22 | [ -e /usr/bin/install-postgres.sh ] 23 | -------------------------------------------------------------------------------- /.github/workflows/reuse.yml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: Copyright (c) 2012-2025 Yegor Bugayenko 2 | # SPDX-License-Identifier: MIT 3 | --- 4 | # yamllint disable rule:line-length 5 | name: reuse 6 | 'on': 7 | push: 8 | branches: 9 | - master 10 | pull_request: 11 | branches: 12 | - master 13 | jobs: 14 | reuse: 15 | timeout-minutes: 15 16 | runs-on: ubuntu-24.04 17 | steps: 18 | - uses: actions/checkout@v4 19 | - uses: fsfe/reuse-action@v5 20 | -------------------------------------------------------------------------------- /.github/workflows/typos.yml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: Copyright (c) 2012-2025 Yegor Bugayenko 2 | # SPDX-License-Identifier: MIT 3 | --- 4 | # yamllint disable rule:line-length 5 | name: typos 6 | 'on': 7 | push: 8 | branches: 9 | - master 10 | pull_request: 11 | branches: 12 | - master 13 | jobs: 14 | typos: 15 | timeout-minutes: 15 16 | runs-on: ubuntu-24.04 17 | steps: 18 | - uses: actions/checkout@v4 19 | - uses: crate-ci/typos@v1.32.0 20 | -------------------------------------------------------------------------------- /.github/workflows/xcop.yml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: Copyright (c) 2012-2025 Yegor Bugayenko 2 | # SPDX-License-Identifier: MIT 3 | --- 4 | # yamllint disable rule:line-length 5 | name: xcop 6 | 'on': 7 | push: 8 | branches: 9 | - master 10 | pull_request: 11 | branches: 12 | - master 13 | jobs: 14 | xcop: 15 | timeout-minutes: 15 16 | runs-on: ubuntu-24.04 17 | steps: 18 | - uses: actions/checkout@v4 19 | - uses: g4s8/xcop-action@master 20 | -------------------------------------------------------------------------------- /.github/workflows/pdd.yml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: Copyright (c) 2012-2025 Yegor Bugayenko 2 | # SPDX-License-Identifier: MIT 3 | --- 4 | # yamllint disable rule:line-length 5 | name: pdd 6 | 'on': 7 | push: 8 | branches: 9 | - master 10 | pull_request: 11 | branches: 12 | - master 13 | jobs: 14 | pdd: 15 | timeout-minutes: 15 16 | runs-on: ubuntu-24.04 17 | steps: 18 | - uses: actions/checkout@v4 19 | - uses: volodya-lombrozo/pdd-action@master 20 | -------------------------------------------------------------------------------- /.github/workflows/yamllint.yml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: Copyright (c) 2012-2025 Yegor Bugayenko 2 | # SPDX-License-Identifier: MIT 3 | --- 4 | # yamllint disable rule:line-length 5 | name: yamllint 6 | 'on': 7 | push: 8 | branches: 9 | - master 10 | pull_request: 11 | branches: 12 | - master 13 | jobs: 14 | yamllint: 15 | timeout-minutes: 15 16 | runs-on: ubuntu-24.04 17 | steps: 18 | - uses: actions/checkout@v4 19 | - uses: ibiqlik/action-yamllint@v3 20 | -------------------------------------------------------------------------------- /.github/workflows/checkmake.yml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: Copyright (c) 2012-2025 Yegor Bugayenko 2 | # SPDX-License-Identifier: MIT 3 | --- 4 | # yamllint disable rule:line-length 5 | name: checkmake 6 | 'on': 7 | push: 8 | branches: 9 | - master 10 | pull_request: 11 | branches: 12 | - master 13 | jobs: 14 | checkmake: 15 | timeout-minutes: 15 16 | runs-on: ubuntu-24.04 17 | steps: 18 | - uses: actions/checkout@v4 19 | - uses: Uno-Takashi/checkmake-action@v2 20 | -------------------------------------------------------------------------------- /.github/workflows/shellcheck.yml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: Copyright (c) 2012-2025 Yegor Bugayenko 2 | # SPDX-License-Identifier: MIT 3 | --- 4 | # yamllint disable rule:line-length 5 | name: shellcheck 6 | 'on': 7 | push: 8 | branches: 9 | - master 10 | pull_request: 11 | branches: 12 | - master 13 | jobs: 14 | shellcheck: 15 | timeout-minutes: 15 16 | runs-on: ubuntu-24.04 17 | steps: 18 | - uses: actions/checkout@v4 19 | - uses: ludeeus/action-shellcheck@master 20 | -------------------------------------------------------------------------------- /rust/Dockerfile: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: Copyright (c) 2012-2025 Yegor Bugayenko 2 | # SPDX-License-Identifier: MIT 3 | 4 | FROM yegor256/ruby:0.0.1 5 | LABEL description="RULTOR image for simple Rust projects" 6 | LABEL version="0.0.1" 7 | 8 | SHELL ["/bin/bash", "-e", "-c", "-o", "pipefail"] 9 | 10 | ENV PATH=${PATH}:${HOME}/.cargo/bin 11 | 12 | RUN curl https://sh.rustup.rs -sSf | bash -s -- -y \ 13 | && echo "export PATH=\${PATH}:\${HOME}/.cargo/bin" >> "${HOME}/.profile" \ 14 | && rustup toolchain install stable 15 | -------------------------------------------------------------------------------- /.github/workflows/make.yml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: Copyright (c) 2012-2025 Yegor Bugayenko 2 | # SPDX-License-Identifier: MIT 3 | --- 4 | # yamllint disable rule:line-length 5 | name: make 6 | 'on': 7 | push: 8 | branches: 9 | - master 10 | pull_request: 11 | branches: 12 | - master 13 | jobs: 14 | make: 15 | timeout-minutes: 30 16 | runs-on: ubuntu-24.04 17 | env: 18 | PLATFORMS: '' 19 | steps: 20 | - uses: actions/checkout@v4 21 | - run: make pull 22 | - run: make -e test 23 | -------------------------------------------------------------------------------- /tests/test-latex.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # SPDX-FileCopyrightText: Copyright (c) 2012-2025 Yegor Bugayenko 4 | # SPDX-License-Identifier: MIT 5 | 6 | set -ex -o pipefail 7 | 8 | pdflatex --version 9 | latexmk --version 10 | bibtex --version 11 | biber --version 12 | l3build --version 13 | gs --version 14 | qpdf --version 15 | texsc --version 16 | texqc --version 17 | inkscape --version 18 | 19 | [[ "$(pdflatex --version)" =~ 2\.6 ]] 20 | 21 | tlmgr install iexec 22 | 23 | echo "hard ffcode" > /tmp/DEPENDS.txt 24 | update-depends.sh /tmp/DEPENDS.txt 25 | -------------------------------------------------------------------------------- /latex/update-depends.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # SPDX-FileCopyrightText: Copyright (c) 2012-2025 Yegor Bugayenko 4 | # SPDX-License-Identifier: MIT 5 | 6 | set -ex -o pipefail 7 | 8 | depends=$1 9 | 10 | if [ ! -e "${depends}" ]; then 11 | echo "The file is absent: ${depends}" 12 | exit 1 13 | fi 14 | 15 | tlmgr option repository ---URL--- 16 | tlmgr --verify-repo=none update --self 17 | 18 | readarray -t packages < <(cut -d' ' -f2 "${depends}" | uniq) 19 | 20 | tlmgr --verify-repo=none install "${packages[@]}" 21 | tlmgr --verify-repo=none update "${packages[@]}" 22 | -------------------------------------------------------------------------------- /.github/workflows/markdown-lint.yml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: Copyright (c) 2012-2025 Yegor Bugayenko 2 | # SPDX-License-Identifier: MIT 3 | --- 4 | # yamllint disable rule:line-length 5 | name: markdown-lint 6 | 'on': 7 | push: 8 | branches: 9 | - master 10 | pull_request: 11 | branches: 12 | - master 13 | paths-ignore: ['paper/**', 'sandbox/**'] 14 | concurrency: 15 | group: markdown-lint-${{ github.ref }} 16 | cancel-in-progress: true 17 | jobs: 18 | markdown-lint: 19 | timeout-minutes: 15 20 | runs-on: ubuntu-24.04 21 | steps: 22 | - uses: actions/checkout@v4 23 | - uses: DavidAnson/markdownlint-cli2-action@v20.0.0 24 | -------------------------------------------------------------------------------- /.github/workflows/bashate.yml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: Copyright (c) 2012-2025 Yegor Bugayenko 2 | # SPDX-License-Identifier: MIT 3 | --- 4 | # yamllint disable rule:line-length 5 | name: bashate 6 | 'on': 7 | push: 8 | branches: 9 | - master 10 | pull_request: 11 | branches: 12 | - master 13 | jobs: 14 | bashate: 15 | timeout-minutes: 15 16 | runs-on: ubuntu-24.04 17 | steps: 18 | - uses: actions/checkout@v4 19 | - uses: actions/setup-python@v5 20 | with: 21 | python-version: 3.11 22 | - run: pip install bashate 23 | - run: | 24 | readarray -t files < <(find . -name '*.sh') 25 | bashate -i E006,E003 "${files[@]}" 26 | -------------------------------------------------------------------------------- /REUSE.toml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: Copyright (c) 2025 Yegor Bugayenko 2 | # SPDX-License-Identifier: MIT 3 | 4 | version = 1 5 | [[annotations]] 6 | path = [ 7 | ".DS_Store", 8 | ".gitattributes", 9 | ".gitignore", 10 | "**.json", 11 | "**.md", 12 | "**.txt", 13 | "**/.DS_Store", 14 | "**/.gitignore", 15 | "**/*.csv", 16 | "**/*.jpg", 17 | "**/*.json", 18 | "**/*.md", 19 | "**/*.pdf", 20 | "**/*.png", 21 | "**/*.svg", 22 | "**/*.txt", 23 | "**/*.vm", 24 | "**/CNAME", 25 | "README.md", 26 | "renovate.json", 27 | ] 28 | precedence = "override" 29 | SPDX-FileCopyrightText = "Copyright (c) 2025 Yegor Bugayenko" 30 | SPDX-License-Identifier = "MIT" 31 | -------------------------------------------------------------------------------- /extras/install-chrome.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # SPDX-FileCopyrightText: Copyright (c) 2012-2025 Yegor Bugayenko 4 | # SPDX-License-Identifier: MIT 5 | 6 | set -ex -o pipefail 7 | 8 | apt-get update --yes --fix-missing 9 | apt-get install --yes chromium-driver 10 | 11 | wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | gpg --dearmor > /etc/apt/trusted.gpg.d/chrome-keyring.gpg 12 | echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" > /etc/apt/sources.list.d/google-chrome.list 13 | apt-get update --yes --fix-missing 14 | apt-get install --yes google-chrome-stable 15 | apt-get remove --yes --purge chromium-driver 16 | apt-get clean 17 | 18 | google-chrome --version 19 | /usr/bin/google-chrome --version 20 | -------------------------------------------------------------------------------- /.github/workflows/actionlint.yml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: Copyright (c) 2012-2025 Yegor Bugayenko 2 | # SPDX-License-Identifier: MIT 3 | --- 4 | # yamllint disable rule:line-length 5 | name: actionlint 6 | 'on': 7 | push: 8 | branches: 9 | - master 10 | pull_request: 11 | branches: 12 | - master 13 | jobs: 14 | actionlint: 15 | timeout-minutes: 15 16 | runs-on: ubuntu-24.04 17 | steps: 18 | - uses: actions/checkout@v4 19 | - name: Download actionlint 20 | id: get_actionlint 21 | run: bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash) 22 | shell: bash 23 | - name: Check workflow files 24 | run: ${{ steps.get_actionlint.outputs.executable }} -color 25 | shell: bash 26 | -------------------------------------------------------------------------------- /haskell/Dockerfile: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: Copyright (c) 2012-2025 Yegor Bugayenko 2 | # SPDX-License-Identifier: MIT 3 | 4 | FROM yegor256/java:0.0.1 5 | LABEL description="RULTOR image for simple Haskell+Java projects" 6 | LABEL version="0.0.1" 7 | 8 | SHELL ["/bin/bash", "-e", "-c", "-o", "pipefail"] 9 | 10 | RUN gpg --batch --recv-keys ECA44F5A172EDAD947F39E3D4275CDA6A29BED43 \ 11 | && curl https://downloads.haskell.org/~ghcup/x86_64-linux-ghcup > /usr/bin/ghcup \ 12 | && chmod +x /usr/bin/ghcup \ 13 | && ghcup config set gpg-setting GPGStrict 14 | 15 | ARG GHC=9.6.7 16 | ARG CABAL=3.12.1.0 17 | 18 | RUN ghcup -v install ghc --isolate /usr/local --force "${GHC}" \ 19 | && ghcup -v install cabal --isolate /usr/local/bin --force "${CABAL}" \ 20 | && cabal update \ 21 | && ghc --version \ 22 | && cabal --version 23 | -------------------------------------------------------------------------------- /extras/install-postgres.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # SPDX-FileCopyrightText: Copyright (c) 2012-2025 Yegor Bugayenko 4 | # SPDX-License-Identifier: MIT 5 | 6 | set -ex -o pipefail 7 | 8 | wget -qO - https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor > /etc/apt/trusted.gpg.d/postgresql-archive-keyring.gpg 9 | echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list 10 | apt-get update --yes --fix-missing 11 | apt-get install --yes libpq-dev 12 | apt-get install --yes postgresql-client-16 postgresql-16 13 | dir=$(realpath "/usr/lib/postgresql"/*) 14 | version=$(basename "${dir}") 15 | apt-get install --yes "postgresql-server-dev-${version}" 16 | apt-get clean 17 | 18 | for c in initdb postgres pg_ctl; do 19 | ln -s "$(realpath "${dir}/bin/${c}")" "/bin/${c}" 20 | done 21 | 22 | postgres --version 23 | -------------------------------------------------------------------------------- /.github/workflows/hadolint.yml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: Copyright (c) 2012-2025 Yegor Bugayenko 2 | # SPDX-License-Identifier: MIT 3 | --- 4 | # yamllint disable rule:line-length 5 | name: hadolint 6 | 'on': 7 | push: 8 | pull_request: 9 | jobs: 10 | hadolint: 11 | timeout-minutes: 15 12 | runs-on: ubuntu-24.04 13 | steps: 14 | - uses: actions/checkout@v4 15 | - uses: hadolint/hadolint-action@v3.1.0 16 | with: 17 | dockerfile: ruby/Dockerfile 18 | - uses: hadolint/hadolint-action@v3.1.0 19 | with: 20 | dockerfile: java/Dockerfile 21 | - uses: hadolint/hadolint-action@v3.1.0 22 | with: 23 | dockerfile: latex/Dockerfile 24 | - uses: hadolint/hadolint-action@v3.1.0 25 | with: 26 | dockerfile: python/Dockerfile 27 | - uses: hadolint/hadolint-action@v3.1.0 28 | with: 29 | dockerfile: rust/Dockerfile 30 | -------------------------------------------------------------------------------- /.github/workflows/copyrights.yml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: Copyright (c) 2012-2025 Yegor Bugayenko 2 | # SPDX-License-Identifier: MIT 3 | --- 4 | # yamllint disable rule:line-length 5 | name: copyrights 6 | 'on': 7 | push: 8 | pull_request: 9 | jobs: 10 | copyrights: 11 | timeout-minutes: 15 12 | runs-on: ubuntu-24.04 13 | steps: 14 | - uses: actions/checkout@v4 15 | - uses: yegor256/copyrights-action@0.0.12 16 | with: 17 | globs: >- 18 | **/LICENSE.txt 19 | **/Makefile 20 | **/*.sh 21 | **/*.yml 22 | **/*.yaml 23 | **/*.java 24 | **/*.xml 25 | **/*.hs 26 | **/*.hi 27 | **/*.cpp 28 | **/*.hpp 29 | **/*.h 30 | **/*.c 31 | **/*.adb 32 | **/*.e 33 | **/*.go 34 | **/*.lisp 35 | **/*.pp 36 | **/*.rs 37 | **/*.xsl 38 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | (The MIT License) 2 | 3 | Copyright (c) 2012-2025 Yegor Bugayenko 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 | -------------------------------------------------------------------------------- /LICENSES/MIT.txt: -------------------------------------------------------------------------------- 1 | (The MIT License) 2 | 3 | Copyright (c) 2012-2025 Yegor Bugayenko 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # A Few Convenient Docker Images 2 | 3 | [![make](https://github.com/yegor256/dockers/actions/workflows/make.yml/badge.svg)](https://github.com/yegor256/dockers/actions/workflows/make.yml) 4 | 5 | Just a collection of convenient Docker images. 6 | Their names speak for themselves. 7 | 8 | * [`yegor256/ruby`](https://hub.docker.com/repository/docker/yegor256/ruby) 9 | * [`yegor256/java`](https://hub.docker.com/repository/docker/yegor256/java) 10 | * [`yegor256/python`](https://hub.docker.com/repository/docker/yegor256/python) 11 | * [`yegor256/latex`](https://hub.docker.com/repository/docker/yegor256/latex) 12 | * [`yegor256/rust`](https://hub.docker.com/repository/docker/yegor256/rust) 13 | 14 | All of them are used by [Rultor] in all our repositories. 15 | 16 | In order to build them all, use Make: 17 | 18 | ```bash 19 | make 20 | ``` 21 | 22 | If doesn't work on macOS, do this: 23 | 24 | ```bash 25 | make PLATFORMS=linux/x86_64 26 | ``` 27 | 28 | When they are all ready, `make push` them to [Docker Hub] 29 | (provided, you are [logged] into it already). 30 | 31 | [Rultor]: https://www.rultor.com 32 | [Docker Hub]: https://hub.docker.com/ 33 | [logged]: https://docs.docker.com/reference/cli/docker/login/ 34 | -------------------------------------------------------------------------------- /python/Dockerfile: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: Copyright (c) 2012-2025 Yegor Bugayenko 2 | # SPDX-License-Identifier: MIT 3 | 4 | FROM yegor256/java:0.0.1 5 | LABEL description="RULTOR image for simple Python+Pip projects" 6 | LABEL version="0.0.1" 7 | 8 | SHELL ["/bin/bash", "-e", "-c", "-o", "pipefail"] 9 | 10 | # hadolint ignore=DL3003 11 | RUN apt-get update \ 12 | && apt-get install --yes --no-install-recommends \ 13 | wget=* \ 14 | build-essential=* \ 15 | libssl-dev=* \ 16 | zlib1g-dev=* \ 17 | libbz2-dev=* \ 18 | libreadline-dev=* \ 19 | libsqlite3-dev=* \ 20 | xz-utils=* \ 21 | tk-dev=* \ 22 | libxml2-dev=* \ 23 | libxmlsec1-dev=* \ 24 | libffi-dev=* \ 25 | liblzma-dev=* \ 26 | && apt-get clean \ 27 | && rm -rf /var/lib/apt/lists/* \ 28 | && cd /tmp \ 29 | && wget --quiet https://www.python.org/ftp/python/3.12.0/Python-3.12.0.tgz \ 30 | && tar -xzf Python-3.12.0.tgz \ 31 | && cd Python-3.12.0 \ 32 | && ./configure --enable-optimizations \ 33 | && make -j "$(nproc)" \ 34 | && make install \ 35 | && cd / \ 36 | && rm -rf /tmp/Python-3.12.0* \ 37 | && ln -sf /usr/local/bin/python3 /usr/bin/python3 \ 38 | && ln -sf /usr/local/bin/python3 /usr/bin/python \ 39 | && ln -sf /usr/local/bin/pip3 /usr/bin/pip3 \ 40 | && ln -sf /usr/local/bin/pip3 /usr/bin/pip \ 41 | && echo "export PATH=\${PATH}:\${HOME}/.local/bin" >> "${HOME}/.profile" \ 42 | && python3 --version \ 43 | && pip3 --version 44 | -------------------------------------------------------------------------------- /latex/Dockerfile: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: Copyright (c) 2012-2025 Yegor Bugayenko 2 | # SPDX-License-Identifier: MIT 3 | 4 | FROM yegor256/ruby:0.0.1 5 | LABEL description="RULTOR image for simple LaTeX projects" 6 | LABEL version="0.0.1" 7 | 8 | WORKDIR /tmp 9 | 10 | SHELL ["/bin/bash", "-e", "-c", "-o", "pipefail"] 11 | 12 | RUN apt-get -y -q update \ 13 | && apt-get -y install --no-install-recommends \ 14 | perl=* \ 15 | inkscape=* \ 16 | aspell=* \ 17 | imagemagick=* \ 18 | ghostscript=* \ 19 | qpdf=* \ 20 | && apt-get clean \ 21 | && rm -rf /var/lib/apt/lists/* 22 | 23 | ENV TL_YEAR=2025 24 | ENV TL_URL=https://ftp.snt.utwente.nl/pub/software/tex/systems/texlive/tlnet 25 | ENV PATH=${PATH}:/usr/local/texlive/${TL_YEAR}/bin/latest 26 | 27 | # hadolint ignore=DL3003 28 | RUN wget -q --no-check-certificate "${TL_URL}/install-tl.zip" \ 29 | && unzip -qq install-tl.zip -d install-tl \ 30 | && cd install-tl/install-tl-* \ 31 | && perl ./install-tl --scheme=scheme-minimal --no-interaction "--repository=${TL_URL}" \ 32 | && ln -s "$(ls "/usr/local/texlive/${TL_YEAR}/bin/")" "/usr/local/texlive/${TL_YEAR}/bin/latest" \ 33 | && cd .. \ 34 | && rm -rf ./install-tl* \ 35 | && echo "export PATH=\${PATH}:/usr/local/texlive/${TL_YEAR}/bin/latest" >> "${HOME}/.profile" \ 36 | && tlmgr init-usertree \ 37 | && tlmgr option repository "${TL_URL}" \ 38 | && tlmgr --verify-repo=none install \ 39 | texliveonfly collection-latex luaotfload l3kernel l3packages latexmk l3build biber xetex collection-fontsrecommended \ 40 | && chmod -R a+w /usr/local/texlive 41 | 42 | RUN gem install texsc -v 0.8.0 \ 43 | && gem install texqc -v 0.8.0 44 | 45 | COPY latex/update-depends.sh /usr/bin 46 | RUN sed -i -E "s|---URL---|${TL_URL}|g" /usr/bin/update-depends.sh 47 | -------------------------------------------------------------------------------- /java/Dockerfile: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: Copyright (c) 2012-2025 Yegor Bugayenko 2 | # SPDX-License-Identifier: MIT 3 | 4 | FROM yegor256/ruby:0.0.1 5 | LABEL description="RULTOR image for simple Java+Maven projects" 6 | LABEL version="0.0.1" 7 | 8 | SHELL ["/bin/bash", "-e", "-c", "-o", "pipefail"] 9 | 10 | ENV MAVEN_OPTS=-Xmx1g 11 | ENV JAVA_OPTS=-Xmx1g 12 | ENV JAVA_VERSION=17 13 | ENV JAVA_HOME=/usr/lib/jvm/java-${JAVA_VERSION} 14 | RUN apt-get --yes --fix-missing update \ 15 | && apt-get --yes --no-install-recommends install ca-certificates-java=* ca-certificates=* "openjdk-${JAVA_VERSION}-jdk=*" \ 16 | && update-ca-certificates \ 17 | && ln -s "/usr/lib/jvm/$(find /usr/lib/jvm -name "java-1.${JAVA_VERSION}*" -exec basename {} \;)" "/usr/lib/jvm/java-${JAVA_VERSION}" \ 18 | && echo "export JAVA_HOME=/usr/lib/jvm/java-${JAVA_VERSION}" >> "${HOME}/.profile" \ 19 | && apt-get clean \ 20 | && rm -rf /var/lib/apt/lists/* 21 | 22 | ENV MAVEN_VERSION=3.9.9 23 | ENV M2_HOME=/usr/local/apache-maven/apache-maven-${MAVEN_VERSION} 24 | RUN echo "export M2_HOME=/usr/local/apache-maven/apache-maven-${MAVEN_VERSION}" >> "${HOME}/.profile" \ 25 | && wget --quiet "https://archive.apache.org/dist/maven/maven-3/${MAVEN_VERSION}/binaries/apache-maven-${MAVEN_VERSION}-bin.tar.gz" \ 26 | && mkdir -p /usr/local/apache-maven \ 27 | && mv "apache-maven-${MAVEN_VERSION}-bin.tar.gz" /usr/local/apache-maven \ 28 | && tar xzvf "/usr/local/apache-maven/apache-maven-${MAVEN_VERSION}-bin.tar.gz" -C /usr/local/apache-maven/ \ 29 | && update-alternatives --install /usr/bin/mvn mvn "${M2_HOME}/bin/mvn" 1 \ 30 | && update-alternatives --config mvn \ 31 | && mvn dependency:get -Dartifact=junit:junit:4.11 32 | 33 | ENV GRADLE_VERSION=9.0.0 34 | RUN wget -q "https://services.gradle.org/distributions/gradle-${GRADLE_VERSION}-bin.zip" -P /tmp \ 35 | && unzip -d /opt "/tmp/gradle-${GRADLE_VERSION}-bin.zip" \ 36 | && chmod a+x "/opt/gradle-${GRADLE_VERSION}/bin/gradle" \ 37 | && ln -s "/opt/gradle-${GRADLE_VERSION}/bin/gradle" /usr/bin/gradle \ 38 | && echo "export PATH=${PATH}:/opt/gradle-${GRADLE_VERSION}/bin" >> "${HOME}/.profile" 39 | -------------------------------------------------------------------------------- /ruby/Dockerfile: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: Copyright (c) 2012-2025 Yegor Bugayenko 2 | # SPDX-License-Identifier: MIT 3 | 4 | FROM ruby:3.4-bullseye 5 | LABEL description="RULTOR image for simple Ruby projects (gems mostly)" 6 | LABEL version="0.0.1" 7 | 8 | WORKDIR /tmp 9 | 10 | SHELL ["/bin/bash", "-e", "-c", "-o", "pipefail"] 11 | 12 | ENV DEBIAN_FRONTEND=noninteractive 13 | 14 | ENV HOME=/root 15 | 16 | RUN apt-get update && apt-get install --yes --no-install-recommends locales=* \ 17 | && sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen \ 18 | && locale-gen \ 19 | && update-locale LANG=en_US.UTF-8 \ 20 | && printf 'LC_ALL=en_US.UTF-8\nLANG=en_US.UTF-8\nLANGUAGE=en_US.UTF-8\n' > /etc/default/locale \ 21 | && printf 'export LC_ALL=en_US.UTF-8\n' >> "${HOME}/.profile" \ 22 | && printf 'export LANG=en_US.UTF-8\n' >> "${HOME}/.profile" \ 23 | && printf 'export LANGUAGE=en_US.UTF-8\n' >> "${HOME}/.profile" \ 24 | && apt-get clean \ 25 | && rm -rf /var/lib/apt/lists/* 26 | 27 | ENV LC_ALL=en_US.UTF-8 28 | ENV LANG=en_US.UTF-8 29 | ENV LANGUAGE=en_US.UTF-8 30 | 31 | RUN apt-get update \ 32 | && apt-get install --yes --no-install-recommends \ 33 | build-essential=* \ 34 | ca-certificates=* \ 35 | curl=* wget=* \ 36 | git=* \ 37 | gnupg2=* \ 38 | jq=* \ 39 | libcurl4-gnutls-dev=* \ 40 | libjpeg-dev=* \ 41 | libmagic-dev=* \ 42 | libxml2-utils=* \ 43 | lsb-release=* \ 44 | openssl=* \ 45 | software-properties-common=* \ 46 | ssh=* \ 47 | sudo=* \ 48 | tree=* \ 49 | unzip=* \ 50 | zip=* \ 51 | zlib1g-dev=* \ 52 | && apt-get clean \ 53 | && rm -rf /var/lib/apt/lists/* 54 | 55 | RUN mkdir -p /etc/apt/keyrings/ \ 56 | && curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc \ 57 | && chmod a+r /etc/apt/keyrings/docker.asc \ 58 | && echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian $(. /etc/os-release && echo "${VERSION_CODENAME}") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null \ 59 | && apt-get update \ 60 | && apt-get --yes --no-install-recommends install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin \ 61 | && apt-get clean \ 62 | && rm -rf /var/lib/apt/lists/* 63 | 64 | ENV GEM_HOME=/usr/local/bundle 65 | RUN echo 'gem: --no-document' >> ~/.gemrc \ 66 | && gem install bundler -v 2.3.26 \ 67 | && gem install xcop -v 0.8.0 \ 68 | && gem install pdd -v 0.23.1 \ 69 | && chmod a+w -R /usr/local/bundle 70 | 71 | ENV PATH=${GEM_HOME}/bin:${PATH} 72 | RUN echo "export PATH=${GEM_HOME}/bin:\${PATH}" >> "${HOME}/.profile" \ 73 | && echo "export GEM_HOME=${GEM_HOME}" >> "${HOME}/.profile" 74 | 75 | COPY extras/ /usr/bin/ 76 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: Copyright (c) 2012-2025 Yegor Bugayenko 2 | # SPDX-License-Identifier: MIT 3 | 4 | .ONESHELL: 5 | .PHONY: all test build push clean ruby latex python rust java haskell 6 | .SHELLFLAGS := -e -o pipefail -c 7 | SHELL := bash 8 | LANGS=ruby java latex python rust haskell 9 | BUILDS=$(addsuffix .build,$(addprefix target/,$(LANGS))) 10 | PUSHES=$(addsuffix .push,$(addprefix target/,$(LANGS))) 11 | TESTS=$(addsuffix .test,$(addprefix target/,$(LANGS))) 12 | EXTRAS=$(shell find extras/ -name '*.sh') 13 | ETESTS=$(addsuffix .extra,$(addprefix target/,$(subst extras/,,$(subst .sh,,$(EXTRAS))))) 14 | PLATFORMS=linux/x86_64,linux/arm64,linux/amd64 15 | 16 | VERSION=0.0.1 17 | 18 | all: test 19 | 20 | test: $(TESTS) $(ETESTS) 21 | 22 | build: $(BUILDS) 23 | 24 | push: $(PUSHES) 25 | 26 | ruby: target/ruby.test $(EXTRAS) 27 | python: target/python.test 28 | rust: target/rust.test 29 | latex: target/latex.test 30 | haskell: target/haskell.test 31 | java: target/java.test 32 | target/ruby.build: $(EXTRAS) 33 | target/java.build: target/ruby.build 34 | target/haskell.build: target/java.build 35 | target/python.build: target/ruby.build target/java.build 36 | target/rust.build: target/ruby.build 37 | target/latex.build: target/ruby.build 38 | 39 | pull: | target 40 | for lang in $(LANGS); do 41 | docker pull "yegor256/$${lang}" 42 | done 43 | 44 | target/%.push: target/%.build target/%.test | target 45 | b=$$(basename "$<") 46 | lang="$${b%.*}" 47 | docker tag "yegor256/$${lang}" "yegor256/$${lang}:$(VERSION)" 48 | docker push "yegor256/$${lang}" 49 | docker push "yegor256/$${lang}:$(VERSION)" 50 | echo $? > "$@" 51 | 52 | target/%.build: %/Dockerfile $(EXTRAS) Makefile | target 53 | lang=$$(dirname "$<") 54 | if [ -n "$(PLATFORMS)" ]; then 55 | docker buildx create --use --name multi-platform-builder || true 56 | docker buildx build --progress=plain --file "$<" \ 57 | "--platform=$(PLATFORMS)" \ 58 | --tag "yegor256/$${lang}" --load . 59 | else 60 | docker buildx build --progress=plain --file "$<" \ 61 | --tag "yegor256/$${lang}" --load . 62 | fi 63 | echo $? > "$@" 64 | 65 | target/%.test: target/%.build Makefile 66 | b=$$(basename "$<") 67 | lang="$${b%.*}" 68 | img=yegor256/$${lang} 69 | docker run --rm "$${img}" pdd --version 70 | docker run --rm "$${img}" /bin/bash -c "$$(cat tests/test-$${lang}.sh)" 71 | docker run --rm "$${img}" /bin/bash -c " 72 | useradd -m -G sudo r 73 | usermod -a -G nogroup r 74 | usermod -a -G ssh r 75 | usermod -a -G r r 76 | usermod -s /bin/bash r 77 | find /root \( -type f -o -type d -maxdepth 1 \) -exec cp -R {} /home/r \; 78 | chown -R r:r /home/r 79 | su --login r --command \"$$(cat tests/test-$${lang}.sh | sed 's|\"|\\\"|g')\" 80 | " 81 | echo $? > "$@" 82 | 83 | target/%.extra: extras/%.sh target/ruby.build Makefile 84 | i=$$(basename "$<") 85 | if [ -n "$(PLATFORMS)" ]; then 86 | docker run --rm --platform=linux/amd64 yegor256/ruby "/usr/bin/$${i}" 87 | else 88 | docker run --rm yegor256/ruby "/usr/bin/$${i}" 89 | fi 90 | echo $? > "$@" 91 | 92 | target: 93 | mkdir -p target 94 | 95 | clean: 96 | rm -rf target 97 | --------------------------------------------------------------------------------