An Introduction to Local Development with Docker Container

4 minute read

Previously I wrote a post about how to setup TV box as a development machine, I cannot take a box everywhere I go, because it is not that convenient to find a power supply, every now and then I get to go outside, I want to work sometimes, I tend to use docker this time, since all you need is a laptop, nothing more.

First things first, you need to get and install docker for Mac, and check docker version to see if it is properly installed:

$ docker --version
Docker version 19.03.13, build 4484c46d9d

Docker Setup

The first thing I do after installation is to set docker image path to externel drive, since it takes too much disk space.

Set disk image location to /Volumes/sandisk/com.docker.docker/ and then click Apply & Restart, a directory called DockerDesktop will be created. Docker Preferences

This step may take a very long time to complete, if docker is stuck in starting, try to quit docker desktop in status bar.

Ubuntu Container Setup

Ubuntu official image can be found in docker hub, for me I pick the LTS version focal:

$ docker pull ubuntu:focal

Run docker container with:

$ docker run -it ubuntu

This will create a container, which can be seen with docker ps or in docker dashboard:

$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
f86b2d00496a        ubuntu              "/bin/bash"         9 seconds ago       Up 8 seconds                            quirky_edison

Now it’s time on board, let’s make all the stuff ready for development:

sed -i s/archive.ubuntu.com/mirrors.tuna.tsinghua.edu.cn/g /etc/apt/sources.list
apt update
apt install -y openssh-client openssh-server rsync net-tools iputils-ping sudo git
apt install -y python3-pip zsh screen ripgrep fd-find vim curl sysstat python-is-python3
apt install -y gcc-aarch64-linux-gnu moreutils libncurses5-dev
apt install -y bison cmake flex libelf-dev zlib1g-dev libfl-dev systemtap-sdt-dev binutils-dev
apt install -y libbpfcc-dev llvm clang libclang-dev netperf arping iperf3

# add user fdbai
adduser --disabled-password --gecos "" fdbai
usermod -aG sudo fdbai

echo '151.101.56.133 raw.githubusercontent.com' >> /etc/hosts
git config --global url."https://gh.api.99988866.xyz/github.com/".insteadof https://github.com

# oh-my-zsh
sh -c "$(wget -O- https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
git config --global oh-my-zsh.hide-status 1

# fzf
git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf
~/.fzf/install


# GNU screen
cat << EOT >> .screenrc
# Turn off that annoying start up message
startup_message off

# scrolling with mouse
termcapinfo xterm* ti@:te@

hardstatus alwayslastline
hardstatus string '%{= kG}[ %{G}%H %{g}][%= %{=kw}%?%-Lw%?%{r}(%{W}%n*%f%t%?(%u)%?%{r})%{w}%?%+Lw%?%?%= %{g}][%{B}%Y-%m-%d %{W}%c %{g}]'
EOT


# pip mirror
mkdir $HOME/.pip
cat << EOT >> $HOME/.pip/pip.conf
[global]
index-url = https://pypi.tuna.tsinghua.edu.cn/simple
EOT


# vim
curl https://j.mp/spf13-vim3 -L > spf13-vim.sh && sh spf13-vim.sh
cd $HOME/.spf13-vim-3
git pull
vim +BundleInstall! +BundleClean +q

cat << EOT >>  ~/.vimrc.local
" Quik close and save
map <leader>q :q<cr>
map <leader>a :qa<cr>
map <leader>x :x<cr>
map <leader>w :w<cr>

map <leader>tn :tabnew
map <leader>te :tabedit
map <leader>tc :tabclose<cr>
map <leader>tm :tabmove
map <leader>to :tabonly<cr>
map <leader>tf :tabfirst<cr>

" Disable scrolloff, whichwrap etc
set whichwrap=
set scrolloff=0
set scrolljump=0
EOT

cat << EOT >>  ~/.vimrc.before.local
" Do not switch to the current file directory
let g:spf13_no_autochdir = 1
EOT

Commit New Docker Image

We can create a new docker image after have all the required packages and tools installed, the syntax is:

docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]

For creating new image, container id is needed:

$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
f86b2d00496a        ubuntu              "/bin/bash"         About an hour ago   Up About an hour                        quirky_edison

$ docker commit f86b2d00496a ubuntu:basic
sha256:05e25b1175855cc1998b3fbae583825c94fc5d87fe55b56e4284d45e91a98ab3

This may take a while, depending on the image size, be patient, if you have host log running, you will see this process:

$ tail -f /Users/fdbai/Library/Containers/com.docker.docker/Data/log/host/com.docker.driver.amd64-linux.log
time="2020-10-26T10:27:31+08:00" level=info msg="proxy >> POST /v1.40/commit?author=&comment=&container=f86b2d00496a&repo=ubuntu&tag=basic\n"
[...]
time="2020-10-26T10:28:24+08:00" level=info msg="proxy << POST /v1.40/commit?author=&comment=&container=f86b2d00496a&repo=ubuntu&tag=basic (52.589429746s)\n"

If image was created successfully, it will appears in the output of docker images:

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED              SIZE
ubuntu              basic               05e25b117585        About a minute ago   700MB
ubuntu              focal               d70eaf7277ea        2 days ago           72.9MB
ubuntu              latest              d70eaf7277ea        2 days ago           72.9MB

Save Container Images

The image created with docker commit is inside Docker.raw, this file is usually too big for backup, so save these container image to a separate file is a practical way for later use, either for backup or for importing.

There are two ways to do this, one way called save which saves image from docker images, the syntax is:

docker save [OPTIONS] IMAGE [IMAGE...]

e.g.

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              basic               05e25b117585        21 minutes ago      700MB
ubuntu              focal               d70eaf7277ea        2 days ago          72.9MB

$ docker save -o focal-basic.save.tar ubuntu:basic
$ ls -l focal-basic.save.tar
-rw-------  1 fdbai  staff  723009536 Oct 26 10:52 focal-basic.save.tar

Another way is to export from current running container, the syntax is:

docker export [OPTIONS] CONTAINER

e.g.

$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
f86b2d00496a        ubuntu              "/bin/bash"         2 hours ago         Up 2 hours                              quirky_edison

$ docker export -o focal-basic.export.tar quirky_edison

Using Docker

$ docker start -ai quirky_edison
$ docker start -ai f86b2d00496a

$ docker start quirky_edison
$ docker exec -u fdbai -w /home/fdbai -it quirky_edison zsh
$ docker exec -u fdbai -w /home/fdbai -it quirky_edison bash