Build the GraalVM executable in a container

This guide walks you through compiling a Ballerina application to a native executable and packing the GraalVM executable in a container.


To complete this part of the guide, you need:

  1. Latest Ballerina Swan Lake distribution
  2. A text editor

    Tip: Preferably, Visual Studio Code with the Ballerina extension installed.

  3. Docker installed and configured in your machine

    Tip: Since the GraalVM native build consumes a significant amount of memory, it is recommended to increase the memory allocated to Docker to at least 8GB and potentially add more CPUs as well. For more details, see How to assign more memory to Docker container.

  4. A command terminal

After the environment is set up, follow the steps below to build the native executable and pack it in a container.

Build the GraalVM executable in a container

  1. Execute the command below to create a Ballerina service package.

    $ bal new hello_docker -t service
  2. Replace the content of the file service.bal with the following.

    import ballerina/http;
    service / on new http:Listener(8080) {
        resource function get greeting() returns string {   
            return "Hello, Docker!";   
  3. Execute bal build --graalvm --cloud=docker to generate the artifacts with the native executable.

    Info: Optionally, you can create a file named Cloud.toml in the package directory to add cloud related configurations. For more information, see Docker and Kubernetes documentation.

    $ bal build --graalvm --cloud=docker
    Compiling source
    Generating artifacts
    Building the native image. This may take a while
    [+] Building 193.8s (13/13) FINISHED                                                                                                                                        docker:default
     => [internal] load .dockerignore                                                                                              0.0s
     => => transferring context: 2B                                                                                                0.0s
     => [internal] load build definition from Dockerfile                                                                           0.0s
     => => transferring dockerfile: 416B                                                                                           0.0s
     => [internal] load metadata for                                                                 3.2s
     => [internal] load metadata for                                                 4.2s
     => [build 1/4] FROM                                                      0.0s
     => [internal] load build context                                                                                              0.2s
     => => transferring context: 38.38MB                                                                                           0.2s
     => [stage-1 1/3] FROM          0.0s
     => CACHED [stage-1 2/3] WORKDIR /home/ballerina                                                                               0.0s
     => CACHED [build 2/4] WORKDIR /app/build                                                                                      0.0s
     => [build 3/4] COPY hello_world.jar .                                                                                         0.1s
     => [build 4/4] RUN native-image -jar hello_world.jar -H:Name=hello_world --no-fallback -H:+StaticExecutableWithDynamicLibC  188.7s
     => [stage-1 3/3] COPY --from=build /app/build/hello_world .                                                                   0.2s 
     => exporting to image                                                                                                         0.3s 
     => => exporting layers                                                                                                        0.2s 
     => => writing image sha256:0129932fea465e620849b5842b42cb8136ab2daabf25e1817a7879207f6d861b                                   0.0s 
     => => naming to                                                                          0.0s 
     Execute the below command to run the generated Docker image: 
            docker run -d -p 8080:8080 hello_world:latest

    The Docker file:

    # Auto Generated Dockerfile
    FROM as build
    WORKDIR /app/build
    COPY hello_world.jar .
    RUN native-image -jar hello_world.jar -H:Name=hello_world --no-fallback -H:+StaticExecutableWithDynamicLibC
    WORKDIR /home/ballerina
    EXPOSE  8080
    COPY --from=build /app/build/hello_world .
    CMD ["./hello_world"]
  4. Execute the Docker image.

    $ docker run -d -p 8080:8080 hello_docker:latest
  5. Test the service with the cURL request below.

    $ curl http://localhost:8080/greeting
    Hello, Docker!