# Building Docker Images

## Cargo Features

The Hyperswitch application server makes extensive use of
[Cargo features][cargo-features] to selectively toggle certain features and
integrations.
The list of features can be found in the `[features]` section in the
[`crates/router/Cargo.toml`][router-manifest] file.

Of these features, the noteworthy ones are the `default` and `release` features:

- `default`: This feature set enables a basic set of necessary features for both
  development and production environments, such as the transactional APIs,
  APIs used by the control center, Stripe compatibility, automatic payment
  retries, in-memory caching, etc.

- `release`: This feature set enables some additional features that are suitable
  for production environments, such as AWS KMS integration, AWS S3 integration,
  AWS SES integration, etc.

Refer to the [documentation on cargo features][cargo-features] to understand how
to select features with Cargo, when building the application server.

## Building with the Dockerfile

The Docker images for the application server and other components can be built
using the [`Dockerfile`][dockerfile] using the below commands, substituting the
Docker image tags with suitable values:

- router:

  ```shell
  docker build \
    --load \
    --file Dockerfile \
    --build-arg "BINARY=router" \
    --tag hyperswitch-router \
    .
  ```

- consumer:

  ```shell
  docker build \
    --load \
    --file Dockerfile \
    --build-arg "BINARY=scheduler" \
    --build-arg "SCHEDULER_FLOW=consumer" \
    --tag hyperswitch-consumer \
    .
  ```

- producer:

  ```shell
  docker build \
    --load \
    --file Dockerfile \
    --build-arg "BINARY=scheduler" \
    --build-arg "SCHEDULER_FLOW=producer" \
    --tag hyperswitch-producer \
    .
  ```

- drainer:

  ```shell
  docker build \
    --load \
    --file Dockerfile \
    --build-arg "BINARY=drainer" \
    --tag hyperswitch-drainer \
    .
  ```

When our Docker images are built using the [`Dockerfile`][dockerfile], the
`cargo` command being run is:

```shell
cargo build --release --features release ${EXTRA_FEATURES}
```

- The `--release` flag specifies that optimized release binaries must be built.
  Refer to the [`cargo build` manual page][cargo-build-manual-page] for more
  information.

- The `--features release` flag specifies that the `release` feature set must be
  enabled for the build.
  Since we do not specify the `--no-default-features` flag to the `cargo build`
  command, the build would have the `default` and `release` features enabled.

- In case you create your own features sets and want to enable them, you can use
  the `${EXTRA_FEATURES}` build argument to specify any additional features that
  would have to be passed to the `cargo build` command.
  The build argument could look as follows:
  `EXTRA_FEATURES="--features feature1,feature2,feature3"`, with actual feature
  names substituted in the command.

## Image Variants on Docker Hub

As of writing this document, we have two image variants available on our Docker
Hub repositories:

- release: These images contain only the tag that was built, and no other
  suffixes, like the `v1.105.1` and `v1.107.0` Docker images.

- standalone: These images contain the tag that was built with a `standalone`
  suffix, like the `v1.105.1-standalone` and `v1.107.0-standalone` Docker images.

The primary difference is that our standalone Docker images do not have some
features enabled by default in order to support hosting of Hyperswitch outside
AWS.
As of writing this document, the standalone images exclude the `email` and
`recon` features from the `release` feature set, while the release images are
built from the Dockerfile without any changes to the codebase after the tag is
checked out.

If you are building custom images and would like to mirror the behavior of our
standalone images, then you'd have to remove the `email` and `recon` features
from the `release` feature set.

## Frequently Asked Questions

### What machine specifications would I need to build release images?

Building release (optimized) images needs significant amount of resources, and
we'd recommend using a machine with at least 8 cores and 16 GB of RAM for this
purpose.
Rust is known to have long compile times, and a codebase of this size will
require a significant time to build, around 45-60 minutes for the above
configuration.

### Build seems to be stuck at "Compiling router/scheduler/analytics/..."

The compilation process involves compiling all of our dependencies and then
compiling our workspace (first-party) crates, among which the biggest one
(in terms of lines of code) is the `router` crate.
Once all the dependencies of the `router` crate have been built, one of the last
ones being built is the `router` crate itself.

As mentioned above, building release images takes a significant amount of time.
It is normal to see nothing else being printed after a line which says
`Compiling router / scheduler / analytics / ...`. We'd suggest waiting
for a while.
If you're still concerned that the compilation process has been stuck for far
too long, you can check if at least one CPU is being utilized by
`cargo` / `docker` using a tool like `htop` (if you can access the machine which
is building the code). Worst case, you can proceed to kill the compilation
process and try again.

[cargo-features]: https://doc.rust-lang.org/cargo/reference/features.html
[router-manifest]: https://github.com/juspay/hyperswitch/blob/main/crates/router/Cargo.toml
[dockerfile]: https://github.com/juspay/hyperswitch/blob/main/Dockerfile
[cargo-build-manual-page]: https://doc.rust-lang.org/cargo/commands/cargo-build.html
