Skip to content

Commit e0f408f

Browse files
author
sangam14
committed
Create Docker-shell.md
1 parent 2bce7bf commit e0f408f

File tree

1 file changed

+314
-0
lines changed

1 file changed

+314
-0
lines changed

intermediate/Docker-shell.md

+314
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,314 @@
1+
## Using Docker for Testing and Development on any Linux Distribution
2+
3+
I will describe how to use docker to help you run shells in arbitrary linux
4+
distributions, preserving your changes.
5+
6+
I will try to keep this short, there is a lot of information about Docker on the
7+
internet of course.
8+
9+
### What is Docker?
10+
11+
Docker is a container system, it runs a linux system as a filesystem (image)
12+
using your existing linux operating system. On other OSes, it shares a
13+
lightweight linux virtual machine between your different linux containers.
14+
15+
### Install Docker
16+
17+
The first step is to install docker. Use your distribution package. On Windows
18+
or Mac, use the installer from the docker hub.
19+
20+
Create an account with docker here:
21+
22+
https://hub.docker.com/
23+
24+
This is where you search for images.
25+
26+
### Configure Docker
27+
28+
On linux, you will want to add yourself to the `docker` group and
29+
reboot/relogin, and enable the docker service:
30+
31+
```bash
32+
sudo usermod -a -G docker $USER
33+
sudo systemctl enable --now docker.service
34+
```
35+
36+
Once you are logged back in, use the:
37+
38+
```bash
39+
docker login
40+
```
41+
42+
command to log into the hub. You may need the `docker-credential-helpers`
43+
package to store your password.
44+
45+
On Windows and Mac you will want to use the GUI to configure things like RAM and
46+
CPU count for your virtual machine and log into the hub. Be generous with your
47+
allotment, but keep in mind that the docker VM generally needs fewer resources
48+
than a traditional VM.
49+
50+
### Docker Images
51+
52+
Now that you have taken care of the preliminaries, I wil describe how to run
53+
shells in arbitrary linux distributions. For the purposes of this guide, I am
54+
using my username `rkitover`, which you will substitute for your own.
55+
56+
The example distribution I will use is Ubuntu 19.04 "Disco".
57+
58+
The name of this image on the hub is `ubuntu:disco`, when you search for images
59+
on the docker hub you will see the name you need to use.
60+
61+
You can use `docker pull` to load an image into your store, or run an image name
62+
directly and it will be automatically downloaded, you will use the latter
63+
option.
64+
65+
### Initial Setup
66+
67+
We need to create the environment to use from our shell launcher script.
68+
69+
Open a root shell in the image like so:
70+
71+
```bash
72+
docker run --name disco -h disco --detach-keys="ctrl-@" -it ubuntu:disco bash -l
73+
```
74+
75+
docker will download the image and open a root shell.
76+
77+
What this command does:
78+
79+
- the container name is set to `disco`
80+
81+
- the hostname of the container in the docker virtual network is set to `disco`
82+
83+
- the hotkey to detach from the shell is set to `CTRL-2`
84+
85+
- the `-i` option means you want an interactive session
86+
87+
- the `-t` option allocates a tty
88+
89+
- `ubuntu:disco` is the image name on the docker hub, local image names will be
90+
checked first
91+
92+
- the rest is the command to run, in this case a `bash` login shell
93+
94+
Now you are going to do some setup to use the image as a development/testing
95+
environemnt. You would do something similar for other distributions, depending
96+
on your needs and the needed commands.
97+
98+
```bash
99+
useradd rkitover
100+
apt update
101+
apt -y upgrade
102+
apt -y install vim tmux tree git build-essential cmake silversearcher-ag sudo locales
103+
cd /etc/sudoers.d
104+
echo 'rkitover ALL = NOPASSWD: ALL' > rkitover
105+
cd
106+
locale-gen en_US.UTF-8
107+
locale-gen ru_RU.UTF-8
108+
```
109+
110+
That should be good, add your user, install some packages (most importantly sudo
111+
and locales), add yourself to sudo, generate locales.
112+
113+
Make sure your `UID` is the same as on the host, generally `1000`.
114+
115+
Notice that you did not set up a home directory, that's because you are going to
116+
use the docker volumes feature to mount your existing host home directory inside
117+
the image. And this is why your UID needs to match.
118+
119+
Now you will need to save your set up image.
120+
121+
Docker is primarily used by building images from scripts called Dockerfiles, to
122+
run canned services, in this case you are doing something entirely different.
123+
124+
Run:
125+
126+
```bash
127+
docker ps -a
128+
```
129+
130+
You will see something like this:
131+
132+
```
133+
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
134+
52ef73929c74 ubuntu:disco "bash -l" 13 minutes ago Exited (0) 2 seconds ago disco
135+
```
136+
137+
this shows that you had a container named `disco` running using the image
138+
`ubuntu:disco` and that it has exited.
139+
140+
You are going to save the modified image in your namespace and remove the
141+
container.
142+
143+
```bash
144+
docker commit disco rkitover/ubuntu:disco
145+
docker rm disco
146+
```
147+
148+
Now running `docker ps -a` again will show an empty table.
149+
150+
### Some Environment Tweaks for Docker
151+
152+
You need to make some changes to your host `$HOME` configuration for shells in
153+
docker to work properly. These changes are harmless.
154+
155+
Edit your `~/.bash_profile`, at the top put:
156+
157+
```bash
158+
export SHELL=/bin/bash
159+
export LANG=en_US.UTF-8
160+
```
161+
162+
or whatever locale you want and set up in the previous step.
163+
164+
Make sure it has something like this in the middle:
165+
166+
```bash
167+
. ~/.bashrc
168+
```
169+
170+
at the bottom put:
171+
172+
```bash
173+
cd ~
174+
```
175+
176+
You may need to add logic to your `~/.bashrc` to detect if you are running in
177+
some container and adjust your aliases and such accordingly. For example I have
178+
this:
179+
180+
```bash
181+
if ! grep -q docker /proc/1/cgroup; then
182+
alias tmux='systemd-run --quiet --scope --user tmux'
183+
fi
184+
```
185+
186+
### The `docker-shell` script
187+
188+
Put the following script in your `~/bin` or wherever you keep such things:
189+
190+
```bash
191+
mkdir -p ~/bin
192+
cd ~/bin
193+
curl -LO 'https://gist.githubusercontent.com/rkitover/fdf8bc9ca55248752507336d580f7dbb/raw/9b793aa1d9a51548c147005154845b792d340124/docker-shell'
194+
chmod +x docker-shell
195+
```
196+
197+
```bash
198+
#!/bin/sh
199+
200+
image=$1
201+
shift
202+
203+
name=${image##*:}
204+
205+
container_exists() {
206+
[ -n "$(docker ps -q -a -f "name=$name" "$@" 2>/dev/null)" ]
207+
}
208+
209+
set -- \
210+
-e DISPLAY="$DISPLAY" \
211+
-e XDG_RUNTIME_DIR="$XDG_RUNTIME_DIR" \
212+
"$@"
213+
214+
# if running, exec another shell in the container
215+
if container_exists; then
216+
exec docker exec \
217+
--detach-keys="ctrl-@" \
218+
"$@" \
219+
-it -u $USER "$name" bash -l
220+
fi
221+
222+
# otherwise launch a new container
223+
docker run --name "$name" -h "$name" \
224+
"$@" \
225+
-v /tmp/.X11-unix:/tmp/.X11-unix \
226+
-v /run/user/$(id -u):/run/user/$(id -u) \
227+
--device=/dev/dri \
228+
-v "$HOME":"$HOME" \
229+
--detach-keys="ctrl-@" \
230+
-it -u $USER $USER/"$image" bash -l
231+
232+
# after the main shell exits, commit image and remove container
233+
if container_exists -f "status=exited"; then
234+
docker commit "$name" $USER/"$image"
235+
236+
docker rm "$name"
237+
fi
238+
```
239+
240+
Some notes:
241+
242+
- the `-e` option sets an environment variable in the shell session
243+
244+
- the `-v` option binds a directory on your host to the container, like a bind
245+
mount
246+
247+
- the `--device` option passes through a host device, this particular setup will
248+
allow running X apps with GPU acceleration on many setups, more on that later
249+
250+
### Entering the Environment
251+
252+
Now try it out, run:
253+
254+
```bash
255+
docker-shell ubuntu:disco
256+
```
257+
258+
you should get a bash shell in your new Ubuntu environment if everything went
259+
well, with a working locale and sudo.
260+
261+
Running the command again in another terminal while this shell is
262+
active will run another shell in the same container.
263+
264+
Once the first shell exits, the image will be committed and the container will
265+
be removed.
266+
267+
You can pass any other arguments to the script, they will be passed to `docker
268+
run` for the first shell and to `docker exec` for subsequent shells.
269+
270+
If you detach with `CTRL-2`, then you can attach again with:
271+
272+
```bash
273+
docker attach disco
274+
```
275+
276+
If you use this feature, you will have to commit your image and clean up the
277+
container yourself as described previously.
278+
279+
You can commit images to any tag or prefix with this script, and they will be
280+
stored under your user namespace. E.g.:
281+
282+
```bash
283+
docker-shell development/ubuntu:latest
284+
```
285+
286+
in this case during initial setup you would commit the image to
287+
`$USER/development/ubuntu:latest`.
288+
289+
### Miscellaneous
290+
291+
You may want to install a cron job to clean up dangling images and dead
292+
containers, something like this:
293+
294+
```bash
295+
#!/bin/sh
296+
297+
docker inspect -f '{{if not .State.Running}}{{.Id}} {{ end }}' $(docker ps -aq) | grep -Ev '^$' | \
298+
xargs docker rm >/dev/null 2>&1
299+
300+
301+
docker image prune -f >/dev/null 2>&1
302+
```
303+
304+
To use GPU acceleration for X11 apps, install the `mesa-utils` package or
305+
equivalent, and more on that here:
306+
307+
http://wiki.ros.org/docker/Tutorials/Hardware%20Acceleration
308+
309+
### Have Fun!
310+
311+
Now when a user complains "your software doesn't work on my distribution X" you
312+
have a powerful recourse to investigate the problem.
313+
314+
There are endless possibilities with this software.

0 commit comments

Comments
 (0)