Problem

You want a Go development environment inside an Alpine Docker container which is set up with a user that has the same UID and GID as your host user.

Solution

We will set up a Dockerfile and two Shell helper-scripts for

  1. building the image
  2. creating the container.

Dockerfile

FROM alpine

ARG GID
ARG HOME
ARG UID
ARG USER

RUN mkdir $HOME

RUN apk update && apk --no-cache add \
    git go less musl-dev shadow vim

RUN useradd -u $UID -g $GID -d $HOME $USER \
    && chown -R $UID:$GID $HOME

USER $USER

RUN mkdir $HOME/bin \
    && echo "export PATH=$HOME/bin:$HOME/go/bin:$PATH" >> $HOME/.profile

WORKDIR $HOME

The package shadow adds the useradd / usermod / etc. commands. We then add a new user and specify the UID, GID and HOME directory. Note that in line 8 we first create the home directory of our user so that we can add custom exports to a .profile file located under $HOME at the end of the Dockerfile.

Shell helper-scripts

Because the docker build command will be somewhat longer due to all the build arguments needed in the Dockerfile, we will use the following helper-script docker_build.sh:

#!/usr/bin/env bash


docker build -t go-env \
  --build-arg UID=$(id -u) --build-arg GID=$(id -g) \
  --build-arg HOME=/home/$(whoami) --build-arg USER=$(whoami) \
  .

Similarly, we create the following docker_run.sh script, which bind-mounts the workspace directory into the container:

#!/usr/bin/env bash

docker run --rm --name go_env -td -v \
  /Users/apoehlmann/workspace/:/home/apoehlmann/workspace \
  go-env sh

That's it.

Run it

We can now execute our scripts (make sure to chmod +x each one of them):

$ ./docker_build.sh 
Sending build context to Docker daemon  9.728kB
Step 1/11 : FROM alpine
 ---> e7d92cdc71fe
Step 2/11 : ARG GID
 ---> Running in a775cc03652d
Removing intermediate container a775cc03652d
 ---> dcae66249a3f
Step 3/11 : ARG HOME
 ---> Running in deab016ca5de
Removing intermediate container deab016ca5de
 ---> e12ac89d2579
Step 4/11 : ARG UID
 ---> Running in a707a171f390
Removing intermediate container a707a171f390
 ---> b5fdd541bb45
Step 5/11 : ARG USER
 ---> Running in 26325d02d4d7
Removing intermediate container 26325d02d4d7
 ---> 91b8dfd2af63
Step 6/11 : RUN mkdir $HOME
 ---> Running in db03fd3e448a
Removing intermediate container db03fd3e448a
 ---> 0cec18c6c629
Step 7/11 : RUN apk update && apk --no-cache add     git go less shadow vim
 ---> Running in 32db8afa84f0
fetch http://dl-cdn.alpinelinux.org/alpine/v3.11/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.11/community/x86_64/APKINDEX.tar.gz
v3.11.3-19-gb3a750a9f7 [http://dl-cdn.alpinelinux.org/alpine/v3.11/main]
v3.11.3-22-gaf29099ec3 [http://dl-cdn.alpinelinux.org/alpine/v3.11/community]
OK: 11258 distinct packages available
fetch http://dl-cdn.alpinelinux.org/alpine/v3.11/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.11/community/x86_64/APKINDEX.tar.gz
(1/27) Installing ca-certificates (20191127-r0)
(2/27) Installing nghttp2-libs (1.40.0-r0)
(3/27) Installing libcurl (7.67.0-r0)
(4/27) Installing expat (2.2.9-r1)
(5/27) Installing pcre2 (10.34-r1)
(6/27) Installing git (2.24.1-r0)
(7/27) Installing libgcc (9.2.0-r3)
(8/27) Installing libstdc++ (9.2.0-r3)
(9/27) Installing binutils (2.33.1-r0)
(10/27) Installing gmp (6.1.2-r1)
(11/27) Installing isl (0.18-r0)
(12/27) Installing libgomp (9.2.0-r3)
(13/27) Installing libatomic (9.2.0-r3)
(14/27) Installing mpfr4 (4.0.2-r1)
(15/27) Installing mpc1 (1.1.0-r1)
(16/27) Installing gcc (9.2.0-r3)
(17/27) Installing musl-dev (1.1.24-r0)
(18/27) Installing go (1.13.4-r1)
(19/27) Installing ncurses-terminfo-base (6.1_p20191130-r0)
(20/27) Installing ncurses-terminfo (6.1_p20191130-r0)
(21/27) Installing ncurses-libs (6.1_p20191130-r0)
(22/27) Installing less (551-r0)
(23/27) Installing linux-pam (1.3.1-r1)
(24/27) Installing shadow (4.7-r1)
(25/27) Installing xxd (8.2.0-r0)
(26/27) Installing lua5.3-libs (5.3.5-r2)
(27/27) Installing vim (8.2.0-r0)
Executing busybox-1.31.1-r9.trigger
Executing ca-certificates-20191127-r0.trigger
OK: 468 MiB in 41 packages
Removing intermediate container 32db8afa84f0
 ---> f0a6e6ed826d
Step 8/11 : RUN useradd -u $UID -g $GID -d $HOME $USER     && chown -R $UID:$GID $HOME
 ---> Running in 7ccf4351e39d
Removing intermediate container 7ccf4351e39d
 ---> f81fd7986d26
Step 9/11 : USER $USER
 ---> Running in 24a23fc7a1d2
Removing intermediate container 24a23fc7a1d2
 ---> 719e6723f63a
Step 10/11 : RUN mkdir $HOME/bin     && echo "export PATH=$HOME/bin:$HOME/go/bin:$PATH" >> $HOME/.profile
 ---> Running in 9eafa052bc05
Removing intermediate container 9eafa052bc05
 ---> b78b6a833a39
Step 11/11 : WORKDIR $HOME
 ---> Running in 9a3fb44234ed
Removing intermediate container 9a3fb44234ed
 ---> 0b655351ac29
Successfully built 0b655351ac29
Successfully tagged go-env:latest

Create a container:

$ ./docker_run.sh 
348546ec1e2446ae79715064afca0ab06e776b3b079b489bbf99ce3d305803d8

Finally log into the container and source the .profile file:

$ docker exec -it go_env /bin/sh
~ $ . .profile 
~ $ echo $PATH
/home/apoehlmann/bin:/home/apoehlmann/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
Getagged mit:
Docker Tutorial Alpine
blog comments powered by Disqus