# Shipping user friendly bash scripts with your Dev Container

**Date:** 2024-02-12  
**Author:** Kees C. Bakker  
**Categories:** bash  
**Tags:** dev containers  
**Original:** https://keestalkstech.com/shipping-user-friendly-bash-scripts-with-your-dev-container/

![Shipping user friendly bash scripts with your Dev Container](https://keestalkstech.com/wp-content/uploads/2024/02/alex-duffy-a-E__y8y5Wo-unsplash.jpg)

---

Currently I'm working on a [small WordPress plugin that does syntax highlighting](https://github.com/KeesCBakker/ktt-wp-code). I have the need to ship some maintenance scripts with my Dev Containers. I want some aliases to interact with the scripts (instead of calling them through `/scripts/actions.sh`. This solution uses a Bash startup file and a custom Dockerfile.

## The idea

My first thought is to copy the scripts to the Dockerfile as expose them like that. I don't like this solution, as it makes our scripts *static*. In a "native" situation we would also be able to edit and execute the scripts. We want this experience in our Dev Containers as well.

My second thought is a startup script. [I already use a startup.sh script to set some container-wide settings](https://keestalkstech.com/2023/06/github-windows-ssh-gpg-devcontainer/#startup-script). Adding script aliases to the startup will *not* work, as the terminal session starts in *parallel* with the startup script.

*Solution: let's ship a [startup file](https://www.gnu.org/software/bash/manual/html_node/Bash-Startup-Files.html#Invoked-as-an-interactive-non_002dlogin-shell:~:text=When%20an%20interactive%20shell%20that%20is%20not%20a%20login%20shell%20is%20started%2C%20Bash%20reads%20and%20executes%20commands%20from%20~/.bashrc%2C%20if%20that%20file%20exists.) that makes the scripts executable and aliases them for the user.*

## .profile

The startup file should do the following:

1. Extract the name of the workspace.
2. Add the scripts directory to the `PATH`.
3. Make the scripts in the directory executable.
4. Alias a script (in our case `release.sh` as `release`).
5. Let the user know how to use the alias.

Let's create a `.profile` file in our `.devcontainer` directory. We'll use it later to copy it as `.bashrc` and `.zshrc` files.

```sh
#!/bin/sh

# figure out workspace 
export WORKSPACE_NAME=$(pwd | awk -F'/' '{for(i=1;i<=NF;i++) if ($i == "workspaces") {print $(i+1); exit}}')
export WORKSPACE_SCRIPT_PATH="/workspaces/$WORKSPACE_NAME/scripts"

# make scripts executable
pushd $WORKSPACE_SCRIPT_PATH > /dev/null
sudo chmod +x *.sh
popd > /dev/null

export PATH="$PATH:$WORKSPACE_SCRIPT_PATH"

# make aliases for easy execution
# alias script_name='script_name.sh'
alias release='release.sh'

# make sure our .wp-now is present to cache
mkdir -p "$WORKSPACE_SCRIPT_PATH/../.wp-now"

# let the user know
echo ""
echo "To release a new version do:"
echo "\$ release [patch|minor|major]"
echo ""
echo "To start the project:"
echo "\$ wp-now start"
echo ""
```

If the `.profile` adheres to [Bourne shell (sh)](https://en.wikipedia.org/wiki/Bourne_shell), it will run in both Bash and ZSH. You can double check it by running a [ShellCheck](https://www.shellcheck.net/): `shellcheck .devcontainer/.profile`.

## Dockerfile

Let's copy the `.profile` file to our docker file:

```docker
# Start with the same base image
FROM mcr.microsoft.com/devcontainers/php:0-8.2

RUN apt-get update \
    && apt-get install -y shellcheck \
    && rm -rf /var/lib/apt/lists/*

# Append the profile to the current .bashrc and .zshrc files
# this makes sure we keep the current behavior like colors and aliases
COPY ./.profile /tmp/.profile
RUN cat /tmp/.profile >> /home/vscode/.bashrc && \
    cat /tmp/.profile >> /home/vscode/.zshrc && \
    rm /tmp/.profile
```

When we now run the dev container we see:

![Output of the terminal showing the information set by the profile.](https://keestalkstech.com/wp-content/uploads/2024/02/image.png)
*Output of the terminal showing the information set by the profile.*

## Final thoughts

Easy peasy. If you want to look at the code, please check out the Dev Container directory on GitHub: [github.com/KeesCBakker/ktt-wp-code/tree/main/.devcontainer](https://github.com/KeesCBakker/ktt-wp-code/tree/main/.devcontainer).

## Changelog

- 2024-11-11: added [implications for adding a .profile as a Bourne Shell script](https://keestalkstech.com/2024/02/shipping-user-friendly-bash-scripts-with-your-dev-container/#the-idea:~:text=If%20the%20.profile%20adheres%20to%20Bourne%20shell%20(sh)%2C%20it%20will%20run%20in%20both%20Bash%20and%20ZSH.%20You%20can%20double%20check%20it%20by%20running%20a%20ShellCheck%3A%20shellcheck%20.devcontainer/.profile.).
- 2024-11-05: added support for ZSH.
- 2024-02-12: initial article.
