Skip to content

OOM during sysimage creation #1031

Open
@ValentinKaisermayer

Description

@ValentinKaisermayer

I'm trying to package a Julia app as a docker image. Since, as of writing this, package relocatability is not solved; hence, this is the only way to share an app.

In my dockerfile I run:

###############################################################################################
# Stage 1: Build Stage
FROM julia:1.11.2-bullseye AS builder

# Install C compiler required for PackageCompiler and clean up afterward to reduce image size
RUN apt-get update && \
    apt-get install -y --no-install-recommends g++ && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

# Set environment for Julia compilation
ENV JULIA_CPU_TARGET=generic

# Create a non-root user and set up directories
RUN useradd --create-home --shell /bin/bash jl && mkdir /home/jl/app && chown -R jl:jl /home/jl/
WORKDIR /home/jl/app

# Switch to non-root user
USER jl

ENV JULIA_DEPOT_PATH "/home/jl/.julia"
ENV JULIA_REVISE "off"
ENV EARLYBIND "true"
ENV JULIA_NUM_PRECOMPILE_TAKS "4"

# Copy dependency files first to leverage Docker caching for dependencies
COPY --chown=jl:jl Project.toml .
COPY --chown=jl:jl deps/ deps/
RUN julia --project -e "using Pkg; Pkg.instantiate(); Pkg.precompile();"

# Copy the full application code and precompile with sysimage
COPY --chown=jl:jl compiled/ compiled/
COPY --chown=jl:jl App/ App/
# copy test data so that precompiling works
COPY --chown=jl:jl data/ data/
RUN julia --project -t auto -O3 --startup-file=no compiled/make.jl

###############################################################################################
# Stage 2: Production Stage
FROM debian:bullseye-slim  
# Install curl (for BinaryProvider) compiler required for PackageCompiler and clean up afterward to reduce image size
RUN apt-get update && \
    apt-get install -y --no-install-recommends curl && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

# Set up a non-root user for running the app
RUN useradd --create-home --shell /bin/bash jl && mkdir /home/jl/app && chown -R jl:jl /home/jl/
WORKDIR /home/jl/app
USER jl

# Set environment variables
ENV JULIA_REVISE "off"
ENV EARLYBIND "true"

# Copy only essential files from the build stage to the production stage
COPY --from=builder /home/jl/app/compiled/App /home/jl/app

# Since Julia's relocatability depends on each package, simply make a symlink to the artifacts directory in the compiled app
RUN mkdir -p /home/jl/.julia/artifacts && ln -s /home/jl/app/share/julia/artifacts /home/jl/.julia/artifacts

# Command to run the application
ENTRYPOINT ["/home/jl/app/bin/App"]
CMD ["--julia-args", "-t", "auto", "-O3", "--startup-file=no"]

and my make.jl file is:

using PackageCompiler

PackageCompiler.create_app(
    "App",
    "compiled/App";
    cpu_target="generic",
    sysimage_build_args=`-O3`,
    precompile_execution_file="compiled/precompile.jl",
    include_transitive_dependencies=false,
    include_lazy_artifacts=true,
    incremental=true,
    # filter_stdlibs=true,
)

I also have a precompile.jl script with a representative workload.
When I run docker build I get as far as to compiling the incremental sysimage. Then I get OOMs. I just have 8 GB of RAM and 2 GB of swap availiable. The same runs fine on a machine with 16 GB or 24 GB RAM.

My question: How can I reduce the resource need of PackageCompiler.jl?

BTW, the secrete sauce is this line:

RUN mkdir -p /home/jl/.julia/artifacts && ln -s /home/jl/app/share/julia/artifacts /home/jl/.julia/artifacts

which solves the relocatable issue, since I copy over the app from the build stage.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions