Dockerizing Phoenix Development (4) The Dockerfile
Tags: docker, elixir, phoenix, postgres
Published: 2021-05-30 18:49:14

This step assembles a Dockerfile in order to develop a Phoenix web server.  It lists the Dockerfile and then explains key lines.  You **will probably** need to make some adjustments for your own use, so check the explanations.

## The Dockerfile (./myp_dev/Dockerfile.alpine)
```
FROM elixir:1.12-alpine

LABEL maintainer="me_myself_i@work"
LABEL version_date="2021-05-20"

RUN apk add --no-cache --update \
        git \
        inotify-tools \
        libpq postgresql-client \
        nodejs npm yarn

ENV  USER="devuser"  UID="1000"  GID="1000"

RUN addgroup  -g $GID  -S $USER  && \
    adduser  -h /apps  -g ""  -G $USER  -S  -D  -u $UID "$USER"

USER $UID:$GID

ENV PATH="/usr/local/lib/elixir/bin:/usr/local/lib/erlang/bin:$PATH"
ENV PATH="/apps/.cache/rebar3/bin:$PATH"

VOLUME /apps
WORKDIR /apps
EXPOSE 4000/tcp

CMD sleep 50000
```

## Lines Explained

```
FROM elixir:1.12-alpine
```
* _Note this means use of the [apk](https://wiki.alpinelinux.org/wiki/Alpine_Linux_package_management) package manager for [Alpine Linux](https://www.alpinelinux.org/) rather than the **apt** utility used with Debian and Ubuntu.  There is a full searchable library of [packages](https://pkgs.alpinelinux.org/packages) available for Alpine Linux._
* _By the time you read this, later editions may be [available](https://hub.docker.com/_/elixir) so **adjust as necessary**_.

```
RUN apk add --no-cache --update \
        git \
        inotify-tools \
        libpq postgresql-client \
        nodejs npm yarn
```
Packages as follows:

* **[git](https://pkgs.alpinelinux.org/package/edge/main/x86_64/git)** _is useful for automated download of libraries, as well as uploading code to [github](https://www.github.com) et cetera._

* **[inotify-tools](https://pkgs.alpinelinux.org/package/edge/main/x86_64/inotify-tools)** _adds into the container kernel so that changes to files can be detected by a running program within the container_.

* **[libpq](https://pkgs.alpinelinux.org/package/edge/main/x86_64/libpq)** _is the shared object/ DLL for access to PostgreSQL_. 

* **[postgresql-client](https://pkgs.alpinelinux.org/package/edge/main/x86_64/postgresql-client)** _adds in the PostgreSQL command line tools such as **psql**_.  _This is not strictly needed and adds ~9MB to the image, but it is convenient to have on hand._

* **[nodejs](https://pkgs.alpinelinux.org/package/edge/main/x86_64/nodejs)** _Javascript interpreter_.

* **[npm](https://pkgs.alpinelinux.org/package/edge/main/x86_64/npm)** & **[yarn](https://pkgs.alpinelinux.org/package/edge/community/x86_64/yarn)** _package managers for JavaScript_.

```
ENV  USER="devuser"  UID="1000"  GID="1000"
```
* _Set some environment variables for use in setting up a user account for you as developer._

* _Matching the UID & GID between your host user account and the developer account in the image is key to using IDE's and other tools. You **MUST** use your own UID and GID here!_

```
RUN addgroup  -g $GID  -S $USER && \
RUN adduser  -h /apps  -g ""  -G $USER  -S  -D  -u $UID "$USER"
```

* _These lines add a new group and a new user within that group._

* _Alpine Linux uses the [BusyBox](https://www.busybox.net) tools to do this; which are different to the Debian/ Ubuntu ones!_  _[Documentation is available](https://www.busybox.net/downloads/BusyBox.html)._

```
USER $UID:$GID
```
* _The remaining few lines are completed as the **devuser**. So signing in as **devuser** will have the $PATH, and start  in the WORKDIR that you would expect._

```
ENV PATH="/usr/local/lib/elixir/bin:/usr/local/lib/erlang/bin:$PATH"
ENV PATH="/apps/.cache/rebar3/bin:$PATH"
```
* _Adds Elixir and Erlang into the $PATH._

```
VOLUME /apps
WORKDIR /apps
```
* _The **/apps/** folder within the container will be the  $HOME folder of the **devuser** account._ 

* _The same folder will also be mapped as a volume to the **./myp_dev/source/** folder of the host user account  (configured via the **docker-compose.yml**)._

```
EXPOSE 4000/tcp
```
* _This allows the default Phoenix web server port to be  mapped to a known port number of the host machine.  Precisely which port number is configured in the **docker-compose.yml**._

```
CMD sleep 50000
```
* _Once a container runs, it wants to run to completion and  then shutdown in an orderly fashion.  We need it to hang  around so we can attach a console and carry out our  development work!_

## Remarks

- An equivalent **Dockerfile** based on Debian or Ubuntu can readily be put together.  Note however that the image will be near to twice the size(!).
- The **inotify-tools** capability will pick up changes originating inside the container, but may not notice changes originating outside the container (e.g. your IDE). It does however need to be present as Phoenix squeals if it isn't.