Use AWS Credentials in a Dev Container
Tags: devcontainers, aws, development, vscode
Published: 2024-01-21 06:51:58

---
title: Use AWS Credentials in a Dev Container
published: true
date: 2024-01-14 00:00:00 UTC
tags: 
canonical_url: https://theindiecoder.cloud/posts/use-aws-credentials-in-a-dev-container/
---

If you work with AWS, you must have used AWS credentials at least once to run commands through the AWS CLI, CDK CLI, or SAM CLI.

When developing in a Dev Container, you don't have access to your local file system. So, if you try to run an AWS command in the Dev Container, you will encounter some sort of "missing credentials" error.

**How can you fix this?**

It is quite easy to overcome this issue. Remember that a Dev Container is a Docker Container. Therefore, you can use a **bind mount** to link the directory and the files that contain AWS credentials configurations (a.k.a. the `.aws` directory).

If you want to read more about Bind Mount, here's the [link](https://docs.docker.com/storage/bind-mounts/).

## Adding a bind mount to a Docker Container
In Docker, you can add bind mounts using the **`--mount`** flag when running **docker run**:

``` bash
docker run --mount type=bind,source=/.aws,target=/home/vscode/.aws,readonly
```

Let's dive into the command and try to understand each part.

First of all, as explained in the [docs](https://docs.docker.com/storage/bind-mounts/), *`--mount` consists of multiple key-value pairs, separated by commas and each consisting of a
key=value pair.*

OBS:
*The order of the key-value pairs is not significant.*


Let's see which keys are set in our command:

- `type`: the type of the mount, which is `bind`. 
- `source`(or `src`): represents the local path to find the directory we want to mount. In this case the path of our `.aws` directory. 
- `target`(or `dst` or `destination`): represents the path where our local directory will be mounted in the container.
- `readonly` option, which is used when the container does not need write access. In our case, the Dev container only need to read credentials, not to write them.

OBS:
*In case you are using SSO to login, you will need to remove `readonly` option because new temporary credentials will be added.*

More details about the `--mount` flag can be found [here](https://docs.docker.com/storage/bind-mounts/#choose-the--v-or---mount-flag).


Now that we have understood how to add a bind mount to a Docker container, let's see how to do this using the devcontainer specification.

## Adding a bind mount in a Dev container defined with devontainer.json.

When using `devontainer.json`, you can set the command under `mounts` property:

``` json
{
    "mounts": [
	    "source=${localEnv:HOME}/.aws,target=/home/vscode/.aws,type=bind,readonly"
	]
}
```

it looks pretty much the same, the only difference is the value of `source`:

`localEnv:HOME`, is a pre-defined variable.
You can find the list of available variables you can use in devcontainer.json [here](https://containers.dev/implementors/json_reference/#variables-in-devcontainerjson).

The semantic here is:

*print the value of HOME variable that is on the local machine.*

In this case I want the value of the variable **HOME**, since I am wokring on mac. For Windows users, the `mounts` the variable to select is **USERPROFILE**. Therefore, the specification property would look like:

``` json
{
    "mounts": [
	    "source=${localEnv:USERPROFILE}/.aws,target=/home/vscode/.aws,type=bind,readonly"
	]
}
```

A note. 

If you want define a devcontainer.json that is not dependent on any specific IDE, you can use the following:

``` json
{
    "mounts": [
	    "source=${localEnv:HOME}/.aws,target=/.aws,type=bind,readonly"
	],
	"containerEnv": {
  	  	"AWS_CONFIG_FILE": "/.aws/config",
  		"AWS_SHARED_CREDENTIALS_FILE": "/.aws/credentials"
  	},
}
```
In this way, you can set any path as your target, but you have to specify the custom config and credentials paths using respectevely, 
`AWS_CONFIG_FILE` and `AWS_SHARED_CREDENTIALS_FILE` env variables.

You can read more about it on the following pages:
- [Getting started with Docker](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-docker.html)
- [Environment variables to configure the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html)


## Checking the result 

How can you check if we actually managed to mount the `.aws` on your Dev Container?

The easiest way is to check in `Docker Desktop`.
If go to `Containers` section and then click on the one of your interest, there you should see something like this:
![Bind Mount](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f4z0ll9n26aax65bks6j.png)

bindmount.png)

Also, we can look at the `Inspect` tab and if you scroll to `Mounts` property, you should see something like the following:
![Inspect tab](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wxnxim8rs1yhnvvz4bk2.png)

Here, you can also see that `readonly` option was applied as well.

## Conclusion

In this article we have seen how to use AWS credentials in a Dev Container.
I have created a [repository](https://github.com/mtheindiecoder/using-aws-credentials-with-devcontainer) on gitHub which contains an example that applies what we have seen today, to run AWS CLI commands.
Enjoy it!

That's all folks! 🚀
Stay tuned!

## References
- [Bind Mounts](https://docs.docker.com/storage/bind-mounts/)
- [docker run command](https://docs.docker.com/engine/reference/commandline/run/#mount)
- [DevContainer Specification](https://containers.dev/implementors/spec/)
- [Merge Logic](https://containers.dev/implementors/spec/#merge-logic)
- [Variables in devcontainer.json](https://containers.dev/implementors/json_reference/#variables-in-devcontainerjson)
- [Getting started with Docker](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-docker.html)
- [Environment variables to configure the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html)