diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..c54bb86 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,37 @@ +# syntax = docker/dockerfile:1.2 + +# We use a multi-stage build to end up with a very small final image +FROM alpine:latest AS builder + +ENV PATH "$PATH:/root/.cargo/bin" + +WORKDIR /usr/src/app + +# Install build dependencies, rustup & rust's nightly build & toolchain +RUN apk update && apk add --no-cache openssl-dev build-base curl && \ + { curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain nightly; } + +# Copy source code over to builder +COPY Cargo.toml Cargo.lock ./ +COPY src/ ./src/ + +# Run the tests, don't want no broken docker image +# And then finally, build the project +# Thank the lords that this article exists +# https://users.rust-lang.org/t/sigsegv-with-program-linked-against-openssl-in-an-alpine-container/52172 +# TODO add what these flags do & why they work +# NOTE: cargo install auto-appends bin to the path +RUN --mount=type=cache,target=/usr/src/app/target RUSTFLAGS="-C target-feature=-crt-static" cargo test && \ + RUSTFLAGS="-C target-feature=-crt-static" cargo install --path . --bin fej --root /usr/local + + +# Now, we create the actual image +FROM alpine:latest + +# Install some dynamic libraries needed for everything to work +RUN apk update && apk add --no-cache openssl libgcc + +# Copy binary over to final image +COPY --from=builder /usr/local/bin/fej /usr/local/bin/fej + +CMD ["/usr/local/bin/fej"] diff --git a/Makefile b/Makefile index c276d79..ab50282 100644 --- a/Makefile +++ b/Makefile @@ -1,36 +1,35 @@ +IMAGE := chewingbever/fej + + all: debug .PHONY: all # Builds debug: - @ ./build -m dev + @ cargo build .PHONY: debug release: - @ ./build -m rel + @ cargo build --release .PHONY: release +image: Dockerfile + @ ./build '$(IMAGE)' +.PHONY: image + push: - @ ./build -m prod -a push + @ ./build '$(IMAGE)' push .PHONY: push # Run run: - @ ./build -m dev -a run + @ RUST_BACKTRACE=1 cargo run --bin fej .PHONY: run -stop: - @ docker stop -t 2 fej -.PHONY: stop - -logs: - @ docker logs -f fej -.PHONY: logs - # Testing test: - @ ./build -m dev -a run -l -- test --no-fail-fast + @ cargo test --no-fail-fast .PHONY: test format: diff --git a/build b/build index d7d86a3..8abbc39 100755 --- a/build +++ b/build @@ -1,27 +1,18 @@ #!/usr/bin/env bash -image="chewingbever/fej" -# Should be either dev or rel -mode="dev" -action="" -attach="--detach" - -while getopts ":i:m:a:l" c; do - case $c in - i ) image="$OPTARG" ;; - m ) mode="$OPTARG" ;; - a ) action="$OPTARG" ;; - l ) attach="" ;; - ? ) exit 1 ;; - esac -done -shift $((OPTIND-1)) +# Simple guard to check input args +[[ $# -eq 1 ]] || [[ $# -eq 2 ]] || { + >&2 echo "Usage: ./build IMAGE [ACTION]" + exit 1 +} # Extract current version from Cargo.toml & get current branch -patch_version=`grep -Po '(?<=version = ").*(?=")' Cargo.toml | head -n1` -major_version=`echo "$patch_version" | sed -E 's/([0-9]+)\.([0-9]+)\.([0-9]+)/\1/'` -minor_version=`echo "$patch_version" | sed -E 's/([0-9]+).([0-9]+).([0-9]+)/\1.\2/'` -branch=`git rev-parse --abbrev-ref HEAD` +patch_version="$(grep -Po '(?<=version = ").*(?=")' Cargo.toml | head -n1)" +major_version="$(echo "$patch_version" | + sed -E 's/([0-9]+)\.([0-9]+)\.([0-9]+)/\1/')" +minor_version="$(echo "$patch_version" | + sed -E 's/([0-9]+).([0-9]+).([0-9]+)/\1.\2/')" +branch="$(git branch --show-current)" if [[ "$branch" = "master" ]]; then tags=("$patch_version" "$minor_version" "$major_version" "latest") @@ -34,58 +25,31 @@ else fi -# First, we build the builder -DOCKER_BUILDKIT=1 docker build -f docker/Dockerfile.builder -t "$image-builder:latest" . - # Run the actual build command -if [ "$mode" = "rel" ]; then - DOCKER_BUILDKIT=1 docker build -t "$image:$tags" -f docker/Dockerfile.rel . +DOCKER_BUILDKIT=1 docker build -t "$1:$tags" . -elif [[ "$mode" = "dev" ]]; then - DOCKER_BUILDKIT=1 docker build -t "$image-dev:$tags" -f docker/Dockerfile.dev . - -else - >&2 echo "Invalid mode." - exit 1 - -fi - -if [[ "$action" = push ]]; then +if [[ "$2" = push ]]; then [[ "$branch" =~ ^develop|master$ ]] || { >&2 echo "You can only push from develop or master." exit 2 } - [[ "$mode" = "rel" ]] || { - >&2 echo "You can only push release builds." - exit 3 - } - for tag in "${tags[@]}"; do # Create the tag - docker tag "$image:$tags" "$image:$tag" + docker tag "$1:$tags" "$1:$tag" # Push the tag - docker push "$image:$tag" + docker push "$1:$tag" # Remove the tag again, if it's not the main tag - [[ "$tag" != "$tags" ]] && docker rmi "$image:$tag" + [[ "$tag" != "$tags" ]] && docker rmi "$1:$tag" done - elif [[ "$action" = run ]]; then - if [[ "$mode" = "dev" ]]; then - # Create caching volumes if needed (they need to be named) - docker volume create fej_build-cache - docker volume create fej_registry-cache - - flags="-v fej_build-cache:/usr/src/app/target -v fej_registry-cache:/root/.cargo/registry" - fi - - docker run $attach $flags \ + elif [[ "$2" = run ]]; then + docker run \ --rm \ --interactive \ --tty \ --publish 8000:8000 \ - --name fej \ - "$image$([[ "$mode" != "rel" ]] && echo "-dev"):$tags" "$@" + "$1:$tags" fi diff --git a/docker/Dockerfile.builder b/docker/Dockerfile.builder deleted file mode 100644 index 84d09ff..0000000 --- a/docker/Dockerfile.builder +++ /dev/null @@ -1,19 +0,0 @@ -# We use a multi-stage build to end up with a very small final image -FROM alpine:latest AS builder - -ARG MODE -ARG RUN_TESTS - -ENV PATH "$PATH:/root/.cargo/bin" -# Needed for proper compiling of openssl-dev -ENV RUSTFLAGS="-C target-feature=-crt-static" - -WORKDIR /usr/src/app - -# Install build dependencies, rustup & rust's nightly build & toolchain -RUN apk update && apk add --no-cache openssl-dev build-base curl && \ - { curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain nightly; } - -# Copy source code over to builder -COPY Cargo.toml Cargo.lock ./ -COPY src/ ./src/ diff --git a/docker/Dockerfile.dev b/docker/Dockerfile.dev deleted file mode 100644 index a1a1e92..0000000 --- a/docker/Dockerfile.dev +++ /dev/null @@ -1,6 +0,0 @@ -FROM chewingbever/fej-builder:latest - -ENV RUST_BACKTRACE=1 - -ENTRYPOINT ["cargo"] -CMD ["run"] diff --git a/docker/Dockerfile.rel b/docker/Dockerfile.rel deleted file mode 100644 index 4d40ef2..0000000 --- a/docker/Dockerfile.rel +++ /dev/null @@ -1,22 +0,0 @@ -FROM chewingbever/fej-builder:latest AS builder - -# And then finally, build the project -# Thank the lords that this article exists -# https://users.rust-lang.org/t/sigsegv-with-program-linked-against-openssl-in-an-alpine-container/52172 -# TODO add what these flags do & why they work -# NOTE: cargo install auto-appends bin to the path -RUN --mount=type=cache,target=/usr/src/app/target \ - --mount=type=cache,target=/root/.cargo/registry \ - cargo install --path . --bin fej --root /usr/local - - -# Now, we create the actual image -FROM alpine:latest - -# Install some dynamic libraries needed for everything to work -RUN apk update && apk add --no-cache openssl libgcc - -# Copy binary over to final image -COPY --from=builder /usr/local/bin/fej /usr/local/bin/fej - -CMD ["/usr/local/bin/fej"]