Bash Functions and Aliases for the Beginning Docker Developer
Tags: bash, docker
Published: 2017-11-13 15:49:06

---
title: Bash Functions and Aliases for the Beginning Docker Developer
published: true
description: You are adept at the Bash shell and regularly define your own functions and aliases, and you're learning how to use Docker and want an easy way of executing the most common operations without having to memorize a completely new set of subcommands, switches and arguments.
tags: bash, docker
---


## Where I'm Coming From

I run MacOS for work and Ubuntu for fun. Unix-y stuff has always appealed to me because of its composability and extensibility.

I use Bash. Always have. It has plenty of features and is extensible. I used Zsh for a while, but found my way back to Bash after a time because it was important to me for my shell to match the script language I use (and I didn't grok Zsh scripting).

Our team at work has recently started a process of migration to an off-premises vendor for hosting. Part of our deployment strategy involves deploying our services and applications to Docker which I've began learning mostly [in anger](https://news.ycombinator.com/item?id=10806244). There are new paradigms, commands, subcommands with switches and all kinds of extras that I've never had to think about before. And I've had to think about deployment and management of services more than ever before. DevOps has finally caught me.

In this post, I don't describe what Docker is, how to build an image, etc. This is strictly about setting up something useful for learning and running the basic and (for me) most ran Docker commands quickly and easily.


## Why do this?

Developers have to know a lot about their tools. Sometimes we find ourselves running the same things over and over. Thankfully, modern shells have features that let us combine multiple commands into easy to remember mnemonics that are short and quick to type. Bash in particular has functions and aliases that can be defined in your profile to lighten the cognitive load of learning all these commands.

I've started gathering the Docker bits into something that's usable for me and I'm sharing them here with you. What follows is a collection of Bash functions and aliases that I've found useful (that is, when I read my `.bash_history` and see the same command run more than 10 times) in working with Docker. 


### Above All Else, Be Aware of Inconsistency

I learned quickly that `docker` and `docker-compose` are similar, but at the same time very different. They both share a number of subcommands with the same name. But be warned that the similarly named subcommands don't necessarily support the same options. The evolution of Docker has been exciting since it took the world by storm, but it's come at the cost of consistency in its commands.


### Function vs Alias

Functions and aliases in Bash are similar on the surface; you make a mnemonic for a long command. They are very different from each other though and it's important to understand why. See [here](https://askubuntu.com/a/163895/1641) for a quick explanation of the difference between a Bash function and alias. If you've ever got a choice between defining an alias vs a function, the Bash manual says:

> For almost every purpose, shell functions are preferred over aliases.

-- [Bash Reference Manual](https://www.gnu.org/software/bash/manual/html_node/Aliases.html)



### Naming Functions and Aliases

Naming is the hardest thing in the world for us as developers. When I am thinking about what to name a shell function, my checklist is:

- Length: has to be short (< 20 characters if possible).
- Descriptive: has to concisely describe the action taken.


The Docker functions below all start with the letter `d` (or `dc` for `docker-compose` commands) followed by the sometimes shortened subcommand followed by any other information. Normally I join compound words with an underscore but for the Docker functions I did not.

Aliases should always be shorter names than a function. You can make them longer if you wish, but ~90% of the time I make them shorter.

### Function Parameter Checking

Shell functions can have parameters passed to them. I'll often have a check at the beginning of the functions I write that looks like this:

```bash

if [ $# -eq 0 ]; then
  echo 'Usage: $FUNCNAME ARG [ARG ...]'
  return 1
fi
```

The `if` test is of course dependent on what the function needs. This snippet says "if no arguments are passed to the function, print out a usage message and return 1". The return code is important if you're using the function in another function or script. The `$FUNCNAME` variable is an internal Bash variable (reference below) that prints out the name of the currently running function. 

## How I Use Functions

### Shell into a Container


Sometimes things don't work as you had expected and you have to take a closer look at a container you've built to see what's going on. You'll need to do that with a shell (or as I've heard it said many times before, "shell into" the container). Docker's `exec` command will run a command. Since I want to start a shell in a specified container, the function below simplifies that for me:


```bash
# Run a bash shell in the specified container.
#
dexbash() {
  if [ $# -ne 1 ]; then
    echo "Usage: $FUNCNAME CONTAINER_ID"
    return 1
  fi
  
  docker exec -it $1 /bin/bash
}

alias deb='dexbash'

```

This should be read as 'docker exec bash'. The `deb` alias shortens this to a nice 3-letter invocation. Why not name the function `deb`? You could. This is your shell and you're free to do what you want. 

When you're running multiple containers with `docker-compose` there's an `exec` command for it too, but be sure to leave off the `-it` options.


```bash
# Run a bash shell in the specified container (with docker-compose).
#
dcexbash() {
  if [ $# -ne 1 ]; then
    echo "Usage: $FUNCNAME CONTAINER_ID"
    return 1
  fi
  
  docker-compose exec $1 /bin/bash
}

alias dceb='dcexbash'
```

Once you're in you can look for files, run probing commands, etc. just as you would in a normal shell. Of course, some of your favorite tools will be missing since this is a Docker container and it has to be kept small.

### Building and Tagging

Sometimes you want to build and sometimes you want to build **and** tag. This is an example of how to make your shell functions smart and demonstrates the power functions have over aliases:

```bash
# Runs Docker build and tag it with the given name.
#
dbt() {
  if [ $# -lt 1 ]; then
    echo "Usage $FUNCNAME DIRNAME [TAGNAME ...]"
    return 1
  fi

  ARGS="$1"
  shift
  if [ $# -ge 2 ]; then
    ARGS="$ARGS -t $@"
  fi

  docker build $ARGS
}
```

This will build or build and tag (with multiple tags) your container.

### Just Some Aliases

Remember, aliases are simply renamed commands with some flags. They take no parameters like functions do but they will append any flags and arguments you add to them on the command line. These are some aliases of my most-used Docker commands.

```bash
alias datt='docker attach'
alias dcb='docker-compose build'
alias dclogs='docker-compose logs'
alias dcu='docker-compose up'
alias ddiff='docker diff'
alias deb='dexbash'
alias dimg='docker images'
alias dins='docker inspect'
alias dps='docker ps'
alias drm='docker rm'
alias drmi='docker rmi'
alias drun='docker run'
alias dstart='docker start'
alias dstop='docker stop'
```

### A Few (More) of My Favorite s/Things/Aliases/

I noted that shell functions are preferable over shell aliases, but sometimes an alias is the right thing for the job. Take this gem for example:

```bash
# Credit to <https://gist.github.com/bastman/5b57ddb3c11942094f8d0a97d461b430#remove-docker-images>
alias dclimg='docker rmi $(docker images --filter "dangling=true" -q --no-trunc)'
```

Imagine you're working on a Docker image and you're building it over and over. What you may not realize as a beginner is that the container that was previously built doesn't simply get overridden! It's still on your hard drive taking up space! When you run a `docker images` (or `dimg` as above if you noticed) you'll see images without a name. This little guy will clean all of those up for you in 1 command!

Another thing I often will do is specify volumes where configuration files go locally so I can edit them quickly and easily. Depending on what I'm working on I may need to restart a container. This one below is a beaut for that:

```bash
# Credit to <https://stackoverflow.com/a/21928864/37776>
alias drestartf='docker start $(docker ps -ql) && docker attach $(docker ps -ql)'
```

## Conclusion

Bash is clearly my favorite shell, and not just for aliases and functions. Other shells have aliases and functions too and these can all be adapted for them. I hope you find these useful if you're using the command line when working with Docker. 

## Docker & Bash Hows


- [Bash Reference Manual: Shell Functions](https://www.gnu.org/software/bash/manual/html_node/Shell-Functions.html)
- [Internal Variables (Bash Shell)](http://tldp.org/LDP/abs/html/internalvariables.html)
- [Removing Docker Containers and Images](https://zaiste.net/posts/removing_docker_containers/)