Skip to content

Commit d931a15

Browse files
authored
Merge pull request #5 from sir-gon/feature/docker
Docker image building
2 parents 1bb3b40 + 8947cf0 commit d931a15

File tree

6 files changed

+415
-22
lines changed

6 files changed

+415
-22
lines changed

.github/workflows/docker-image.yml

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
---
2+
3+
name: Docker Image CI
4+
5+
on: # yamllint disable-line rule:truthy
6+
push:
7+
branches: ["main"]
8+
pull_request:
9+
# The branches below must be a subset of the branches above
10+
branches: ["main"]
11+
workflow_dispatch:
12+
13+
env:
14+
IMAGE_NAME: algorithm-exercises-rust
15+
ARTIFACT_NAME: algorithm-exercises-rust_${{ github.sha }}
16+
17+
jobs:
18+
19+
build:
20+
name: "Build Docker images"
21+
runs-on: ubuntu-24.04
22+
steps:
23+
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
24+
25+
- name: Set up Docker Buildx
26+
uses: docker/setup-buildx-action@v3
27+
28+
- name: "LINT: Build and push"
29+
uses: docker/build-push-action@v6
30+
with:
31+
context: .
32+
target: lint
33+
outputs: |
34+
type=docker,dest=/tmp/${{ env.ARTIFACT_NAME }}_lint.tar
35+
tags: |
36+
${{ env.IMAGE_NAME }}:lint
37+
- name: "LINT: Upload artifact"
38+
uses: actions/upload-artifact@v4
39+
with:
40+
name: ${{ env.ARTIFACT_NAME }}_lint
41+
path: /tmp/${{ env.ARTIFACT_NAME }}_lint.tar
42+
43+
- name: "TEST: Build and push"
44+
uses: docker/build-push-action@v6
45+
with:
46+
context: .
47+
target: testing
48+
outputs: |
49+
type=docker,dest=/tmp/${{ env.ARTIFACT_NAME }}_test.tar
50+
tags: |
51+
${{ env.IMAGE_NAME }}:test
52+
- name: "TEST: Upload artifact"
53+
uses: actions/upload-artifact@v4
54+
with:
55+
name: ${{ env.ARTIFACT_NAME }}_test
56+
path: /tmp/${{ env.ARTIFACT_NAME }}_test.tar
57+
58+
- name: "PRODUCTION: Build and push"
59+
uses: docker/build-push-action@v6
60+
with:
61+
context: .
62+
target: production
63+
outputs: |
64+
type=docker,dest=/tmp/${{ env.ARTIFACT_NAME }}_prod.tar
65+
tags: |
66+
${{ env.IMAGE_NAME }}:latest
67+
${{ env.IMAGE_NAME }}:${{ github.sha }}
68+
- name: "PRODUCTION: Upload artifact"
69+
uses: actions/upload-artifact@v4
70+
with:
71+
name: ${{ env.ARTIFACT_NAME }}_prod
72+
path: /tmp/${{ env.ARTIFACT_NAME }}_prod.tar
73+
74+
lint:
75+
name: "Run in docker: LINT"
76+
runs-on: ubuntu-24.04
77+
needs: build
78+
steps:
79+
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
80+
81+
- name: Download artifact
82+
uses: actions/download-artifact@v5
83+
with:
84+
name: ${{ env.ARTIFACT_NAME }}_lint
85+
path: /tmp/
86+
87+
- name: Load image
88+
run: |
89+
docker load --input /tmp/${{ env.ARTIFACT_NAME }}_lint.tar
90+
docker image ls -a
91+
92+
- name: Run lint
93+
run: >
94+
docker
95+
compose --profile lint
96+
run --rm ${{ env.IMAGE_NAME }}-lint
97+
make lint
98+
99+
test:
100+
name: "Run in docker: TEST"
101+
runs-on: ubuntu-24.04
102+
needs: build
103+
steps:
104+
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
105+
106+
- name: Download artifact
107+
uses: actions/download-artifact@v5
108+
with:
109+
name: ${{ env.ARTIFACT_NAME }}_test
110+
path: /tmp/
111+
112+
- name: Load image
113+
run: |
114+
docker load --input /tmp/${{ env.ARTIFACT_NAME }}_test.tar
115+
docker image ls -a
116+
117+
- name: Run test
118+
run: >
119+
docker
120+
compose --profile test
121+
run --rm ${{ env.IMAGE_NAME }}-test
122+
make test
123+
124+
# yamllint disable rule:line-length
125+
# security:
126+
# name: "Snyk Container"
127+
# runs-on: ubuntu-24.04
128+
# needs: build
129+
# permissions:
130+
# actions: read
131+
# contents: read
132+
# security-events: write
133+
# steps:
134+
# - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
135+
# - name: Download artifact
136+
# uses: actions/download-artifact@v4
137+
# with:
138+
# name: ${{ env.ARTIFACT_NAME }}_prod
139+
# path: /tmp/
140+
141+
# - name: Load image
142+
# run: |
143+
# docker load --input /tmp/${{ env.ARTIFACT_NAME }}_prod.tar
144+
# docker image ls -a
145+
146+
# - name: Run Snyk to check Docker image for vulnerabilities
147+
# # Snyk can be used to break the build when it detects vulnerabilities.
148+
# # In this case we want to upload the issues to GitHub Code Scanning
149+
# continue-on-error: true
150+
# uses: snyk/actions/docker@master
151+
# env:
152+
# # yamllint disable rule:line-length
153+
# # In order to use the Snyk Action you will need to have a Snyk API token.
154+
# # See https://docs.snyk.io/integrations/ci-cd-integrations/github-actions-integration#getting-your-snyk-token
155+
# # or you can sign up for free at https://snyk.io/login
156+
# # yamllint enable rule:line-length
157+
# SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
158+
# with:
159+
# image: ${{ env.IMAGE_NAME }}:${{ github.sha }}
160+
# args: --file=Dockerfile
161+
# # yamllint disable rule:line-length
162+
# # https://github.com/github/codeql-action/issues/2187#issuecomment-2043220400
163+
# - name: Replace security-severity undefined for license-related findings
164+
# run: |
165+
# sed -i 's/"security-severity": "undefined"/"security-severity": "0"/g' snyk.sarif
166+
# sed -i 's/"security-severity": "null"/"security-severity": "0"/g' snyk.sarif
167+
# # yamllint enable rule:line-length
168+
# - name: Upload result to GitHub Code Scanning
169+
# uses: github/codeql-action/upload-sarif@v3
170+
# with:
171+
# sarif_file: 'snyk.sarif'
172+
# yamllint enable rule:line-length
173+
174+
scan:
175+
name: "Trivy"
176+
runs-on: ubuntu-24.04
177+
needs: build
178+
permissions:
179+
actions: read
180+
contents: read
181+
security-events: write
182+
steps:
183+
- name: Download artifact
184+
uses: actions/download-artifact@v5
185+
with:
186+
name: ${{ env.ARTIFACT_NAME }}_prod
187+
path: /tmp/
188+
189+
- name: Load image
190+
run: |
191+
docker load --input /tmp/${{ env.ARTIFACT_NAME }}_prod.tar
192+
docker image ls -a
193+
194+
- name: Run Trivy vulnerability scanner (cli report)
195+
uses: aquasecurity/trivy-action@0.33.1
196+
with:
197+
image-ref: ${{ env.IMAGE_NAME }}:${{ github.sha }}
198+
format: 'table'
199+
env:
200+
TRIVY_DB_REPOSITORY: ${{ vars.TRIVY_DB_REPOSITORY }}
201+
202+
- name: Run Trivy vulnerability scanner (sarif report)
203+
uses: aquasecurity/trivy-action@0.33.1
204+
with:
205+
image-ref: ${{ env.IMAGE_NAME }}:${{ github.sha }}
206+
format: 'sarif'
207+
output: 'trivy-results.sarif'
208+
env:
209+
TRIVY_DB_REPOSITORY: ${{ vars.TRIVY_DB_REPOSITORY }}
210+
211+
- name: Upload Trivy scan results to GitHub Security tab
212+
uses: github/codeql-action/upload-sarif@v3
213+
with:
214+
sarif_file: 'trivy-results.sarif'

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,8 @@ name = "algorithm-exercises-rust"
33
version = "0.1.0"
44
edition = "2024"
55

6+
[lib]
7+
name = "exercises"
8+
crate-type = ["rlib", "cdylib"]
9+
610
[dependencies]

Dockerfile

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
ARG BASE_IMAGE_VERSION=rust:1.89.0-alpine3.20
2+
FROM ${BASE_IMAGE_VERSION} AS init
3+
4+
ENV WORKDIR=/app
5+
WORKDIR ${WORKDIR}
6+
7+
RUN apk add --update --no-cache make
8+
9+
# cargo-chef to cache dependencies https://crates.io/crates/cargo-chef
10+
11+
###############################################################################
12+
13+
FROM init AS builder
14+
15+
RUN apk add --no-cache musl-dev
16+
RUN cargo install cargo-chef
17+
18+
# sources
19+
COPY ./src ${WORKDIR}/src
20+
COPY ./Cargo.lock ${WORKDIR}/Cargo.lock
21+
COPY ./Cargo.toml ${WORKDIR}/Cargo.toml
22+
COPY ./Makefile ${WORKDIR}/
23+
24+
# dependencies
25+
RUN make dependencies
26+
27+
# build
28+
RUN ls -alhR && \
29+
make build/debug && \
30+
make build/release && \
31+
ls -alhR
32+
33+
CMD ["make", "build"]
34+
35+
###############################################################################
36+
37+
FROM builder AS development
38+
39+
# CMD []
40+
41+
CMD ["make", "build"]
42+
43+
###############################################################################
44+
45+
FROM builder AS lint
46+
47+
RUN rustup component add clippy
48+
RUN \
49+
apk add --update --no-cache nodejs npm yamllint && \
50+
npm install -g --ignore-scripts markdownlint-cli && \
51+
rm -rf /var/lib/apt/lists/*
52+
53+
# Code source
54+
COPY ./src ${WORKDIR}/src
55+
COPY ./Cargo.lock ${WORKDIR}/Cargo.lock
56+
COPY ./Cargo.toml ${WORKDIR}/Cargo.toml
57+
COPY ./recipe.json ${WORKDIR}/recipe.json
58+
COPY ./Makefile ${WORKDIR}/
59+
60+
# markdownlint conf
61+
COPY ./.markdownlint.yaml ${WORKDIR}/
62+
63+
# yamllint conf
64+
COPY ./.yamllint ${WORKDIR}/
65+
COPY ./.yamlignore ${WORKDIR}/
66+
COPY ./.gitignore ${WORKDIR}/
67+
68+
RUN cargo chef cook --release --recipe-path recipe.json
69+
70+
CMD ["make", "lint"]
71+
72+
###############################################################################
73+
74+
FROM development AS testing
75+
76+
ENV WORKDIR=/app
77+
WORKDIR ${WORKDIR}
78+
79+
RUN mkdir -p ${WORKDIR}/target
80+
COPY --from=builder ${WORKDIR}/target/debug ${WORKDIR}/target
81+
82+
CMD ["make", "test"]
83+
84+
###############################################################################
85+
86+
FROM alpine:3.20 AS production
87+
88+
ENV LOG_LEVEL=INFO
89+
ENV BRUTEFORCE=false
90+
ENV WORKDIR=/app
91+
WORKDIR ${WORKDIR}
92+
93+
RUN apk add --update --no-cache make
94+
95+
COPY ./Makefile ${WORKDIR}/
96+
COPY --from=builder ${WORKDIR}/target/release/lib*.rlib ${WORKDIR}/
97+
# COPY --from=builder ${WORKDIR}/target/release/lib*.dylib ${WORKDIR}/
98+
99+
# create a non-root user to run our application
100+
ENV USER=app
101+
ENV GROUPNAME=$USER
102+
ENV UID=12345
103+
ENV GID=23456
104+
105+
RUN addgroup \
106+
--gid "$GID" \
107+
"$GROUPNAME" \
108+
&& adduser \
109+
--disabled-password \
110+
--gecos "" \
111+
--home "$(pwd)" \
112+
--ingroup "$GROUPNAME" \
113+
--no-create-home \
114+
--uid "$UID" \
115+
$USER
116+
117+
RUN ls -alhR
118+
119+
CMD ["make", "run"]

0 commit comments

Comments
 (0)