diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index a3f8dbab..d6adff6f 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -2,9 +2,14 @@ name: Docker Image CI on: push: - branches: [ "main" ] + branches: ["main"] pull_request: - branches: [ "main" ] + branches: ["main"] + workflow_dispatch: + +env: + REGISTRY: ghcr.io + IMAGE_NAME: restsend/rustpbx jobs: build: @@ -14,29 +19,47 @@ jobs: packages: write steps: - - uses: actions/checkout@v4 - - - name: Log in to Container registry - if: github.event_name == 'push' - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Build Docker image - run: | - tag=$(date +%Y%m%d) - if [[ "${{ github.event.head_commit.message }}" =~ \[latest\] ]]; then - tag=latest - fi - docker build . --tag ghcr.io/restsend/rustpbx:$tag - - - name: Push Docker image - if: github.event_name == 'push' - run: | - tag=$(date +%Y%m%d) - if [[ "${{ github.event.head_commit.message }}" =~ \[latest\] ]]; then - tag=latest - docker push ghcr.io/restsend/rustpbx:$tag - fi \ No newline at end of file + - uses: actions/checkout@v4 + + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + + - name: Install Cross + uses: taiki-e/install-action@v2 + with: + tool: cross + + - name: Build Binaries + run: | + cross build --release --target x86_64-unknown-linux-gnu --features cross + cross build --release --target aarch64-unknown-linux-gnu --features cross + + # Organize binaries for Docker Packaging + mkdir -p bin/amd64 bin/arm64 + cp target/x86_64-unknown-linux-gnu/release/rustpbx bin/amd64/ + cp target/x86_64-unknown-linux-gnu/release/sipflow bin/amd64/ + cp target/aarch64-unknown-linux-gnu/release/rustpbx bin/arm64/ + cp target/aarch64-unknown-linux-gnu/release/sipflow bin/arm64/ + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to Container registry + if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push Docker image + uses: docker/build-push-action@v6 + with: + context: . + platforms: linux/amd64,linux/arm64 + push: ${{ github.event_name == 'workflow_dispatch' || (github.event_name == 'push' && contains(github.event.head_commit.message, '[latest]')) }} + tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest + cache-from: type=gha + cache-to: type=gha,mode=max + provenance: false + sbom: false diff --git a/Cargo.toml b/Cargo.toml index 5fc80b2d..980776a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,7 @@ addon-archive = ["flate2"] addon-transcript = [] commerce = ["addon-wholesale"] default = ["opus", "console", "addon-acme", "addon-transcript", "addon-archive"] +cross = ["aws-lc-rs/bindgen"] perfcli-bin = [] text2wav-bin = [] wav2text-bin = [] @@ -125,6 +126,7 @@ socket2 = "0.5" zstd = "0.13" hound = "3.5" minimp3 = "0.5" +aws-lc-rs = { version = "1", optional = true } [dev-dependencies] tempfile = "3.24.0" diff --git a/Cross.toml b/Cross.toml new file mode 100644 index 00000000..77fabfc3 --- /dev/null +++ b/Cross.toml @@ -0,0 +1,5 @@ +[target.x86_64-unknown-linux-gnu] +dockerfile = "./Dockerfile.cross-x86_64" + +[target.aarch64-unknown-linux-gnu] +dockerfile = "./Dockerfile.cross-aarch64" diff --git a/Dockerfile b/Dockerfile index 50b002f2..7ed3cd3c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,32 +1,44 @@ -FROM rust:bookworm AS rust-builder -RUN apt-get update && apt-get install -y libasound2-dev libopus-dev cmake -RUN mkdir /build -ADD . /build/ -WORKDIR /build -RUN --mount=type=cache,target=/build/.cargo/registry \ - --mount=type=cache,target=/build/target/release/incremental\ - --mount=type=cache,target=/build/target/release/build\ - cargo build --release --bin rustpbx --bin sipflow - -FROM debian:bookworm +FROM debian:bookworm-slim + LABEL maintainer="shenjindi@miuda.ai" -RUN --mount=type=cache,target=/var/apt apt-get update && apt-get install -y ca-certificates tzdata libopus0 -ENV DEBIAN_FRONTEND=noninteractive +LABEL org.opencontainers.image.source="https://github.com/restsend/rustpbx" +LABEL org.opencontainers.image.description="A SIP PBX implementation in Rust" + +# Set environment variables +ARG DEBIAN_FRONTEND=noninteractive ENV LANG=C.UTF-8 +ENV TZ=UTC + +# Install runtime dependencies +RUN --mount=type=cache,target=/var/cache/apt \ + apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates \ + tzdata \ + libopus0 \ + && rm -rf /var/lib/apt/lists/* +# Create application directory structure WORKDIR /app -COPY --from=rust-builder /build/static /app/static -COPY --from=rust-builder /build/src/addons/acme/static /app/static/acme -COPY --from=rust-builder /build/src/addons/transcript/static /app/static/transcript -COPY --from=rust-builder /build/src/addons/queue/static /app/static/queue - -COPY --from=rust-builder /build/target/release/rustpbx /app/rustpbx -COPY --from=rust-builder /build/target/release/sipflow /app/sipflow -COPY --from=rust-builder /build/templates /app/templates -COPY --from=rust-builder /build/src/addons/acme/templates /app/templates/acme -COPY --from=rust-builder /build/src/addons/archive/templates /app/templates/archive -COPY --from=rust-builder /build/src/addons/queue/templates /app/templates/queue -COPY --from=rust-builder /build/src/addons/transcript/templates /app/templates/transcript -COPY --from=rust-builder /build/config/sounds /app/sounds +RUN mkdir -p /app/config /app/sounds /app/templates + +# Automatically pick the correct binary based on the architecture being built +# We expect binaries to be placed in bin/amd64/ and bin/arm64/ by the build script +ARG TARGETARCH +COPY bin/${TARGETARCH}/rustpbx /app/rustpbx +COPY bin/${TARGETARCH}/sipflow /app/sipflow + +# Copy static resources +COPY ./static /app/static +COPY ./templates /app/templates +COPY ./config/sounds /app/sounds + +# Copy addon static and templates +COPY ./src/addons/acme/static /app/static/acme +COPY ./src/addons/transcript/static /app/static/transcript +COPY ./src/addons/queue/static /app/static/queue +COPY ./src/addons/acme/templates /app/templates/acme +COPY ./src/addons/archive/templates /app/templates/archive +COPY ./src/addons/queue/templates /app/templates/queue +COPY ./src/addons/transcript/templates /app/templates/transcript ENTRYPOINT ["/app/rustpbx"] diff --git a/Dockerfile.cross-aarch64 b/Dockerfile.cross-aarch64 new file mode 100644 index 00000000..13ef7bb1 --- /dev/null +++ b/Dockerfile.cross-aarch64 @@ -0,0 +1,25 @@ +FROM ghcr.io/cross-rs/aarch64-unknown-linux-gnu:main + +# Install clang, libclang (for bindgen), and dependencies +RUN apt-get update && apt-get install -y \ + cmake \ + pkg-config \ + clang \ + llvm \ + libclang-dev \ + crossbuild-essential-arm64 \ + && rm -rf /var/lib/apt/lists/* + +# Install cross-compiled libs for ARM64 +RUN dpkg --add-architecture arm64 && \ + apt-get update && \ + apt-get install -y libopus-dev:arm64 || true && \ + rm -rf /var/lib/apt/lists/* + +# Bake all cross-compilation environment variables into the image +ENV LIBCLANG_PATH=/usr/lib/llvm-10/lib +ENV CC=clang +ENV CXX=clang++ +ENV PKG_CONFIG_PATH=/usr/lib/aarch64-linux-gnu/pkgconfig +ENV PKG_CONFIG_SYSROOT_DIR=/usr/aarch64-linux-gnu +ENV PKG_CONFIG_ALLOW_CROSS=1 diff --git a/Dockerfile.cross-x86_64 b/Dockerfile.cross-x86_64 new file mode 100644 index 00000000..1713fd41 --- /dev/null +++ b/Dockerfile.cross-x86_64 @@ -0,0 +1,8 @@ +FROM ghcr.io/cross-rs/x86_64-unknown-linux-gnu:main + +# Install clang, libclang (for bindgen), and dependencies +RUN apt-get update && apt-get install -y \ + cmake \ + pkg-config \ + libopus-dev \ + && rm -rf /var/lib/apt/lists/*