Powerbuilding With Fly

When you deploy to Fly, you are deploying an image to the Fly infrastructure. Fly currently uses Docker images for this purpose, for widest compatibility. We're going to take a look at some features available which can power-up your image building.

Identifying Your Build

When you deploy, the flyctl application looks for instructions to build the image in a Dockerfile or creates a builder VM to do the image build. Let’s start with the flags that control where flyctl looks for things.

  • -c, --config filename : It all starts with the config file, which is assumed to be fly.toml in the current directory. Of course you may be building multiple different applications out of the same directory, or just be very organized and have a directory for your different configurations. Whatever the case, the --config option will let you point at a different configuration file.
  • --dockerfile filename : If you are building an image without a builder, flyctl looks for a file called Dockerfile to get its build instructions. Again, if you are building and deploying multiple different applications out of the same directory this can be a problem, which is why this option exists. It tells flyctl to use the filename as the docker file to do the build with.

Controlling the Build

So, now we can tell flyctl what config and docker file we want to use. The next part of taking control of the build applies to any invocation of flyctl where a docker file is involved and that’s --build-args.

But let’s first rewind back into some docker commands. ARG and ENV both deal with variables that can be set in the build process. The ARG command allows variables to be specified that are taken from the build command and used during the build process. The ENV command allows variables to be created that will become environment variables set within the image when it starts running.

Using a combination of these, it’s possible to take a command-line argument and turn it into a runtime environment variable. Consider, for example, that we want to set the port that an NGINX server runs on. We may have had something like:

  ENV NGINX_PORT=8080

in the docker file. To make that controllable from the command line we can replace that with:

  ARG NGINX_PORT=8080
  ENV NGINX_PORT=${NGINX_PORT}

The ARG command makes a variable called NGINX_PORT and sets it to a default of 8080. The ENV command creates an environment variable also called NGINX_PORT. This variable will live on into the running version of the image and can be used by scripts within it to control applications running in the image. It takes its value from the ARG setting of NGINX_PORT through the expansion of ${NGINX_PORT} which refers specifically to the ARG variable and thus will expand to either the default or the passed-in value.

Which leaves the question of how to set that ARG value with flyctl. That’s where --build-args comes in. You can use this option to pass a number of name/value pairs over to the build process. So for our example above we could do:

  flyctl deploy --build-args NGINX_PORT=4000

This will set the build argument which will override the default of the environment variable.

When to Use --build-args

It may look like this is a good way to pass credentials and other sensitive data to your Fly applications, but it isn’t. This is built for non-sensitive data as the information is baked into the image and could be retrievable. If it’s sensitive information you want to pass to the application, check out Fly Secrets which are securely stored and injected, as environment variables, into the application when the image starts running on the Fly platform.