An Introduction to Local Development with Docker Container
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.
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