diff --git a/Library/Resources/Files/docker_file b/Library/Resources/Files/docker_file new file mode 100644 index 0000000..a20ddca --- /dev/null +++ b/Library/Resources/Files/docker_file @@ -0,0 +1,87 @@ +# ================================ +# Build image +# ================================ +FROM swift:6.0-noble as build + +# Install OS updates +RUN export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true \ + && apt-get -q update \ + && apt-get -q dist-upgrade -y \ + && apt-get install -y libjemalloc-dev \ + && rm -rf /var/lib/apt/lists/* + +# Set up a build area +WORKDIR /build + +# First just resolve dependencies. +# This creates a cached layer that can be reused +# as long as your Package.swift/Package.resolved +# files do not change. +COPY ./Package.* ./ +RUN swift package resolve + +# Copy entire repo into container +COPY . . + +# Build the application, with optimizations, with static linking, and using jemalloc +RUN swift build -c release \ + --product "App" \ + --static-swift-stdlib \ + -Xlinker -ljemalloc + +# Switch to the staging area +WORKDIR /staging + +# Copy main executable to staging area +RUN cp "$(swift build --package-path /build -c release --show-bin-path)/App" ./ + +# Copy static swift backtracer binary to staging area +RUN cp "/usr/libexec/swift/linux/swift-backtrace-static" ./ + +# Copy resources bundled by SPM to staging area +RUN find -L "$(swift build --package-path /build -c release --show-bin-path)/" -regex '.*\.resources$' -exec cp -Ra {} ./ \; + +# Copy any resources from the public directory and views directory if the directories exist +# Ensure that by default, neither the directory nor any of its contents are writable. +RUN [ -d /build/public ] && { mv /build/public ./public && chmod -R a-w ./public; } || true + +# ================================ +# Run image +# ================================ +FROM ubuntu:noble + +# Make sure all system packages are up to date, and install only essential packages. +RUN export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true \ + && apt-get -q update \ + && apt-get -q dist-upgrade -y \ + && apt-get -q install -y \ + libjemalloc2 \ + ca-certificates \ + tzdata \ +# If your app or its dependencies import FoundationNetworking, also install `libcurl4`. + # libcurl4 \ +# If your app or its dependencies import FoundationXML, also install `libxml2`. + # libxml2 \ + && rm -r /var/lib/apt/lists/* + +# Create a hummingbird user and group with /app as its home directory +RUN useradd --user-group --create-home --system --skel /dev/null --home-dir /app hummingbird + +# Switch to the new home directory +WORKDIR /app + +# Copy built executable and any staged resources from builder +COPY --from=build --chown=hummingbird:hummingbird /staging /app + +# Provide configuration needed by the built-in crash reporter and some sensible default behaviors. +ENV SWIFT_BACKTRACE=enable=yes,sanitize=yes,threads=all,images=all,interactive=no,swift-backtrace=./swift-backtrace-static + +# Ensure all further commands run as the hummingbird user +USER hummingbird:hummingbird + +# Let Docker bind to port 8080 +EXPOSE 8080 + +# Start the Hummingbird service when the image is run, default to listening on 8080 in production environment +ENTRYPOINT ["./App] +CMD ["--hostname", "0.0.0.0", "--port", "8080"] diff --git a/Library/Resources/Files/package b/Library/Resources/Files/package index a06a7a1..9d28cb6 100644 --- a/Library/Resources/Files/package +++ b/Library/Resources/Files/package @@ -8,7 +8,7 @@ let package = Package( .macOS(.v10_15) ], products: [ - .executable(name: "app", targets: ["App"]), + .executable(name: "App", targets: ["App"]), .library(name: "AppLibrary", targets: ["AppLibrary"]) ], dependencies: [ diff --git a/Library/Sources/Internal/Enumerations/File.swift b/Library/Sources/Internal/Enumerations/File.swift index 6fd4fb9..eccac90 100644 --- a/Library/Sources/Internal/Enumerations/File.swift +++ b/Library/Sources/Internal/Enumerations/File.swift @@ -1,4 +1,5 @@ enum File: String { + case dockerFile = "docker_file" case dockerIgnore = "docker_ignore" case gitIgnore = "git_ignore" case license @@ -14,6 +15,7 @@ extension File { var fileName: String { switch self { + case .dockerFile: "Dockerfile" case .dockerIgnore: ".dockerignore" case .gitIgnore: ".gitignore" case .license: "LICENSE" diff --git a/Test/Sources/Cases/Internal/Enumerations/FileTests.swift b/Test/Sources/Cases/Internal/Enumerations/FileTests.swift index 5c0960e..35f1d5c 100644 --- a/Test/Sources/Cases/Internal/Enumerations/FileTests.swift +++ b/Test/Sources/Cases/Internal/Enumerations/FileTests.swift @@ -43,6 +43,7 @@ struct FileTests { private extension FileTests { enum Expectation { static let fileNames: [String] = [ + "Dockerfile", ".dockerignore", ".gitignore", "LICENSE", @@ -51,6 +52,7 @@ private extension FileTests { ] static let filePaths: [String] = [ + "Dockerfile", ".dockerignore", ".gitignore", "LICENSE", @@ -63,6 +65,7 @@ private extension FileTests { "Resources/Files", "Resources/Files", "Resources/Files", + "Resources/Files", "Resources/Files" ] }