From 23b4d2c17f9e57cd99b3c4843fc74546b2870aea Mon Sep 17 00:00:00 2001 From: Slava <20563034+veaceslavdoina@users.noreply.github.com> Date: Mon, 17 Feb 2025 21:11:37 +0200 Subject: [PATCH] initial commit --- .github/workflows/docker-qemu.yml | 45 +++++++ .github/workflows/docker.yml | 133 ++++++++++++++++++++ Dockerfile | 19 +++ LICENSE-APACHE-2.0 | 199 ++++++++++++++++++++++++++++++ LICENSE-MIT | 19 +++ README.md | 157 +++++++++++++++++++++++ 6 files changed, 572 insertions(+) create mode 100644 .github/workflows/docker-qemu.yml create mode 100644 .github/workflows/docker.yml create mode 100644 Dockerfile create mode 100644 LICENSE-APACHE-2.0 create mode 100644 LICENSE-MIT create mode 100644 README.md diff --git a/.github/workflows/docker-qemu.yml b/.github/workflows/docker-qemu.yml new file mode 100644 index 0000000..1c9d29c --- /dev/null +++ b/.github/workflows/docker-qemu.yml @@ -0,0 +1,45 @@ +name: Docker with QEMU + +on: + workflow_dispatch: + inputs: + nim_version: + description: Nim version (2.0.14) + required: true + type: string + platforms: + description: Platforms (linux/amd64,linux/arm64) + required: false + type: string + default: linux/amd64,linux/arm64 + +env: + DOCKER_FILE: Dockerfile + DOCKER_REPO: codexstorage/nim-lang + PLATFORMS: ${{ inputs.platforms }} + NIM_VERSION: ${{ inputs.nim_version }} + +jobs: + docker: + runs-on: ubuntu-latest + steps: + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build and push + uses: docker/build-push-action@v6 + with: + platforms: ${{ env.PLATFORMS }} + push: true + tags: ${{ env.DOCKER_REPO }}:${{ env.NIM_VERSION }} + build-args: | + NIM_VERSION=${{ env.NIM_VERSION }} diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 0000000..af0c87a --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,133 @@ +name: Docker + +on: + workflow_dispatch: + inputs: + nim_version: + description: Nim version (2.0.14) + required: true + type: string + +env: + DOCKER_FILE: Dockerfile + DOCKERHUB_REPO: codexstorage/nim-lang + NIM_VERSION: ${{ inputs.nim_version }} + amd64_builder: ubuntu-22.04 + arm64_builder: ubuntu-22.04-arm + +jobs: + compute: + name: Compute matrix + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.matrix.outputs.matrix }} + steps: + - name: Compute matrix + id: matrix + uses: fabiocaccamo/create-matrix-action@v5 + with: + matrix: | + os {linux}, arch {amd64}, builder {${{ env.amd64_builder }}} + os {linux}, arch {arm64}, builder {${{ env.arm64_builder }}} + + # Build platform specific image + build: + needs: compute + strategy: + fail-fast: true + matrix: + include: ${{ fromJson(needs.compute.outputs.matrix) }} + + name: Build ${{ matrix.os }}/${{ matrix.arch }} + runs-on: ${{ matrix.builder }} + env: + PLATFORM: ${{ format('{0}/{1}', 'linux', matrix.arch) }} + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Docker - Meta + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.DOCKERHUB_REPO }} + + - name: Docker - Set up Buildx + uses: docker/setup-buildx-action@v3 + + - name: Docker - Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Docker - Build and Push by digest + id: build + uses: docker/build-push-action@v6 + with: + context: . + file: ${{ env.DOCKER_FILE }} + platforms: ${{ env.PLATFORM }} + push: true + build-args: | + NIM_VERSION=${{ env.NIM_VERSION }} + labels: ${{ steps.meta.outputs.labels }} + outputs: type=image,name=${{ env.DOCKERHUB_REPO }},push-by-digest=true,name-canonical=true,push=true + + - name: Docker - Export digest + run: | + mkdir -p /tmp/digests + digest="${{ steps.build.outputs.digest }}" + touch "/tmp/digests/${digest#sha256:}" + + - name: Docker - Upload digest + uses: actions/upload-artifact@v4 + with: + name: digests-${{ matrix.arch }} + path: /tmp/digests/* + if-no-files-found: error + retention-days: 1 + + # Publish multi-platform image + publish: + name: Publish multi-platform image + runs-on: ubuntu-latest + needs: build + steps: + - name: Docker - Variables + run: | + # Set tags + echo "TAGS=${{ env.DOCKER_REPO }}:${{ env.NIM_VERSION }}" >> $GITHUB_ENV + + - name: Docker - Download digests + uses: actions/download-artifact@v4 + with: + path: /tmp/digests + pattern: digests-* + merge-multiple: true + + - name: Docker - Set up Buildx + uses: docker/setup-buildx-action@v3 + + - name: Docker - Meta + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.DOCKERHUB_REPO }} + tags: ${{ env.TAGS }} + + - name: Docker - Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Docker - Create manifest list and push + working-directory: /tmp/digests + run: | + docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ + $(printf '${{ env.DOCKERHUB_REPO }}@sha256:%s ' *) + + - name: Docker - Inspect image + run: | + docker buildx imagetools inspect ${{ env.DOCKERHUB_REPO }}:${{ steps.meta.outputs.version }} diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..b668cbf --- /dev/null +++ b/Dockerfile @@ -0,0 +1,19 @@ +ARG IMAGE=${IMAGE:-ubuntu:24.04} +ARG NIM_VERSION=${NIM_VERSION:-2.0.14} +ARG HOME=${HOME:-/root} + +FROM ${IMAGE} +ARG NIM_VERSION +ARG HOME + +WORKDIR ${HOME} +RUN apt-get update && \ + apt-get install -y curl git gcc make && rm -rf /var/lib/apt/lists/* && \ + curl https://raw.githubusercontent.com/emizzle/nimv/refs/heads/master/nimv.sh | bash -s "${NIM_VERSION}" && \ + rm -rf "${HOME}/.nimv/${NIM_VERSION}/Nim/.git" && \ + rm -rf "${HOME}/.nimv/${NIM_VERSION}/Nim/dist" && \ + rm -rf "${HOME}/.nimv/${NIM_VERSION}/Nim/tests" && \ + rm -rf "${HOME}/.nimv/${NIM_VERSION}/Nim/nimcache" && \ + rm -rf "${HOME}/.nimv/${NIM_VERSION}/Nim/csources_v2" + +ENV PATH=${HOME}/.nimble/bin:${PATH} diff --git a/LICENSE-APACHE-2.0 b/LICENSE-APACHE-2.0 new file mode 100644 index 0000000..cbd5c75 --- /dev/null +++ b/LICENSE-APACHE-2.0 @@ -0,0 +1,199 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSE-MIT b/LICENSE-MIT new file mode 100644 index 0000000..9cf1062 --- /dev/null +++ b/LICENSE-MIT @@ -0,0 +1,19 @@ +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..3fabe79 --- /dev/null +++ b/README.md @@ -0,0 +1,157 @@ +# Nim lang Docker images + +## Description + + At Codex, we are using [Nim](https://nim-lang.org) programming language. Some of our projects are using pre-compiled Nim in Docker for Docker images to simplify and speed up the builds. + + Also, we are using multi-arch Docker images and for that it is required to have multi-arch source images and we have the following issues with that + - :hourglass_flowing_sand: [Make Nim docker images official?](https://forum.nim-lang.org/t/9983) + - :hourglass_flowing_sand: [Provide official docker image #515](https://github.com/nim-lang/RFCs/issues/515) + - :x: [moigagoo/nimage](https://github.com/moigagoo/nimage) - Only amd64, outdated + - :scroll: [theAkito/docker-nim](https://github.com/theAkito/docker-nim) - License, outdated + - :hammer_and_wrench: [arm support for Linux #23](https://github.com/nim-lang/choosenim/issues/23) + + Code in the repository provides a simple way to build multi-arch Docker images with a required Nim version. However, builds are triggered manually. + + We are using GitHub Actions and rely on [nimv](https://github.com/emizzle/nimv) for Nim installation. + + +## Build your own images + + 1. Fork the repository. + 2. Add GitHub Actions secrets - `DOCKERHUB_USERNAME` and `DOCKERHUB_TOKEN`. + 3. Adjust workflow with your repository name. + 4. Run workflow and pass required [Nim version](https://github.com/nim-lang/Nim/tags). + + +## Build manually + + [Multi-platform builds](https://docs.docker.com/build/building/multi-platform/) + + +### On separate VMs + +
+Build guide + +### Build Docker images on separate VMs + + 1. Run `amd64`(`cx32` ,`cpx31`) and `arm64`(`cax21`) VMs on Hetzner + + 2. Install Docker + + 3. Clone repository + ```shell + git clone + ``` + + 4. Define variables + ```shell + repository="codexstorage/nim-lang" + nim_version="2.0.14" + ``` + + 5. Run the build on each VM + ```shell + docker build \ + --tag nim-lang:"${nim_version}" \ + --build-arg NIM_VERSION="${nim_version}" \ + --file Dockerfile . + ``` + + 6. Login to DockerHub + ```shell + docker login -u + ``` + + 7. Push image and get the digest on each VM + ```shell + docker image tag nim-lang:"${nim_version}" "${repository}:${nim_version}" + + docker image push ${repository}:${nim_version} + ``` + + We will get a digest for each image and we need to define appropriate variables + ```shell + amd64="sha256:43c1ea16d34528b3f195e18ca21f69987a01daaf0ddd5d94b252d37ebace2f5c" + arm64="sha256:4b4b3d6617c9bc698adefd0a27d1d18c5236016b92ee7ddc8c42311586568d91" + ``` + + 8. Create a manifest list for multi-arch image and push it from on one of the VM + ```shell + docker buildx imagetools create \ + -t "${repository}:${nim_version}" \ + "${amd64}" \ + "${arm64}" + ``` + +Duration +| Platform | Build | Push | Size | +| -------- | ------------ | ----------- | ------- | +| `amd64` | `8m20.221s` | `1m17.620s` | `659MB` | +| `arm64` | `10m20.591s` | `0m48.888s` | `676MB` | + +TOTAL: ~ `11m09s` + +
+ + +### On a single VM + +
+Build guide + +### Build Docker images on a single VM + + 1. Run `amd64`(`cx32` ,`cpx31`) VM on Hetzner + + 2. Install Docker + + 3. Clone repository + ```shell + git clone + ``` + + 4. Define variables + ```shell + repository="codexstorage/nim-lang" + nim_version="2.0.14" + ``` + + 5. Create a custom builder + ```shell + docker buildx create \ + --name container-builder \ + --driver docker-container \ + --bootstrap --use + ``` + + 6. Login to DockerHub + ```shell + docker login -u + ``` + + 7. Run the build for multiple platforms + ```shell + docker buildx build \ + --tag "${repository}:${nim_version}" \ + --build-arg NIM_VERSION="${nim_version}" \ + --platform linux/amd64,linux/arm64 \ + --push \ + --file Dockerfile . + ``` + +Duration +| Platform | Build | Push | Size | +| -------- | ------------ | ----------- | ------- | +| `amd64` | `-` | `-` | `613MB` | +| `arm64` | `13m55.177s` | `0m42.444s` | `425MB` | + +TOTAL: ~ `14m35s` + +
+ + +## Known issues + + 1. We are using [nimv](https://github.com/emizzle/nimv) which requires bash, so alpine images will not work.