Builds
CI
Each CI/CD pipeline has its own syntax and configuration. Below are examples for GitHub Actions and Gitlab Pipelines.
Github Actions
name: Docker Image Build & Push
on:
release:
types: [created]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build-and-push-image:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Log in to the Container registry
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
- name: Build and push Docker image
uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
Gitlab Pipelines
stages:
- build
- push
variables:
DOCKER_VERSION: 25.0.2
before_script:
- export IMAGE_TAG="$CI_REGISTRY_IMAGE:$CI_COMMIT_TAG"
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
services:
- docker:$DOCKER_VERSION-dind
build_push:
stage: build
image: docker:$DOCKER_VERSION
tags:
- ti
script:
- docker build -t $IMAGE_TAG .
- docker push $IMAGE_TAG
only:
- tags
Dockerfiles
There are many ways to write a Dockerfile. Below are examples for Streamlit, Golang and Remix.js
Streamlit
ARG POETRY_VERSION=1.4
FROM python:3.12-slim as base
WORKDIR /streamlit
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONFAULTHANDLER=1 \
PYTHONUNBUFFERED=1
EXPOSE 8501
FROM base as poetry
ARG POETRY_VERSION
ENV POETRY_CACHE_DIR=/opt/.poetry-cache \
PIP_DEFAULT_TIMEOUT=100 \
PIP_DISABLE_PIP_VERSION_CHECK=1 \
PIP_IGNORE_INSTALLED=1 \
PIP_NO_CACHE_DIR=1
# hadolint ignore=DL3013
RUN pip install --upgrade pip setuptools \
&& pip install poetry=="${POETRY_VERSION}"
COPY pyproject.toml poetry.lock* ./
# hadolint ignore=SC1091
RUN python -m venv /venv \
&& . /venv/bin/activate \
&& poetry install --only main \
--no-root --no-interaction --no-ansi
COPY <<-EOT /entrypoint.sh
#!/usr/bin/env sh
set -e
. /venv/bin/activate
exec "\$@"
EOT
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
FROM poetry as dev
# hadolint ignore=SC1091
RUN . /venv/bin/activate \
&& poetry install \
--no-root --no-interaction --no-ansi
COPY . .
CMD ["streamlit", "run", "./app/π _Home.py"] # replace with your streamlit app
FROM base as prod
COPY --from=poetry /venv /venv
ENV PATH="/venv/bin:${PATH}"
COPY . .
CMD ["streamlit", "run", "./app/π _Home.py", "--server.port=8501", "--server.address=0.0.0.0"] # replace with your streamlit app
Golang
FROM golang:1.22-alpine AS builder
WORKDIR /build
COPY go.mod go.sum main.go ./
RUN go mod tidy \
&& CGO_ENABLED=0 go build
FROM alpine:3.19 as runtime
RUN addgroup -S app \
&& adduser -S -G app app
WORKDIR /home/app
COPY --from=builder /build/app .
RUN chown -R app:app ./
USER app
CMD ["./app"]
Remix.js
FROM node:20.2.0-alpine3.18 as base
FROM base as deps
WORKDIR /app
COPY package*.json ./
RUN npm install
FROM deps AS builder
WORKDIR /app
COPY . .
RUN npm run build
FROM deps AS prod-deps
WORKDIR /app
RUN npm install --production
FROM base as runner
WORKDIR /app
RUN addgroup --system --gid 1001 remix
RUN adduser --system --uid 1001 remix
USER remix
COPY --from=prod-deps --chown=remix:remix /app/package*.json ./
COPY --from=prod-deps --chown=remix:remix /app/node_modules ./node_modules
COPY --from=builder --chown=remix:remix /app/build ./build
COPY --from=builder --chown=remix:remix /app/public ./public
EXPOSE 3000
ENTRYPOINT [ "node", "node_modules/.bin/remix-serve", "build/index.js"]
Last updated