-
Notifications
You must be signed in to change notification settings - Fork 4
/
docker-without-docker.slide
293 lines (167 loc) · 7.37 KB
/
docker-without-docker.slide
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
Docker Without Docker
Recurse Center
16 Apr 2015
Aditya Mukerjee
http://www.adityamukerjee.net
@chimeracoder
*
.image 88x31.png
* Some common questions
- What is Docker? Do I really need it?
- How does Docker actually work?
- How can I set up a single dev environment to work on any computer?
- My code works on my computer. Now how do I put it on a production server?
- Can't I just write code and have it "just work" everywhere?
- Package managers suck. What's a better way?
- Can I make my virtual machine run faster?
- Is it possible to run Docker containers without even running Docker?
* Wouldn't it be nice if
- We could use `git` to manage an entire server or desktop?
- We could provision/deprovision an entire machine with a single command?
* Why not virtualize
- Performance
- Interoperability (inter-communication)
* What is an operating system ("distro")?
- At its core, your OS is just a bunch of files
- Along with an `/sbin/init` file
- Different distributions distribute different files
That's basically it.
.image rootdir.png
* Inspecting processes
.image psauxinit.png
.image pstreeinit.png
* But what's actually in /sbin/init?
- There is *nothing*particularly*special* about what goes here!
- ...But it's almost always the same thing
- `sysvinit` (1983 - ~2010)
- `systemd` (2010 - ?)
*Within*9*days,*all*of*the*top*10*Linux*distributions*will*use*systemd*by*default,*or*descend*from*one*that*does.*
* What tools does systemd provide?
- `systemctl` (system management, daemonization, etc.)
- `journactl` (logging)
- `systemd-analyze` (system profiling)
- `machinectl` (machine management)
These are all *already* available on any machine using systemd
* How do you create a distribution from scratch?
0. Create a directory that represents the new root directory (ie, "/")
1. Move all the right files there, either manually, or with a tool like deboostrap, pacstrap, yum, etc.)
2) Tar your directory and ship it
Congratulations! This directory is a pseudo-snapshot of your new distro!
* Where does Docker come in?
- Docker can also create these 'snapshots', using a `Dockerfile`
.code Dockerfile
Build and run:
$ docker build -t bashtest .
$ docker run -it bashtest
(as with Git hashes, you can use the container ID or a prefix instead of the name)
- Question: What runs as PID 1?
* Dissecting the Dockerfile
.code Dockerfile
$ docker ps
$ docker exec <container> ps aux
* Can I access this 'snapshot'?
- Yes!
$ docker export <container-hash> > img.tar
Let's inspect that:
$ mkdir ~/bashtestcontainer
$ tar -C ~/bashtestcontainer -xvf img.tar
* What's inside the tarfile?
.image dockerimagetarcontents.png
Does this look familiar?
* Can I do this without Docker?
- Yes!
$ mkdir debian-tree
$ debootstrap --arch=amd64 unstable debian-tree
.image debiantreecontents.png
Does *this* look familiar?
* How do we run the Debian image, though?
- The *systemd-nspawn* command runs a command or OS in a lightweight namespace container
- _"In_many_ways_it_is_similar_to_chroot(1),_but_more_powerful_since_it_fully_virtualizes_the_file_system_hierarchy,_as_well_as_the_process_tree,_the_various_IPC_subsystems_and_the_host_and_domain_name."_
* Let's try this out
$ systemd-nspawn -D debian-tree/ /bin/echo "hello, outside world!"
$ systemd-nspawn -D debian-tree/ /bin/bash
$ systemd-nspawn -D debian-tree/ /sbin/init
* We can manage our containers with machinectl
$ machinectl list
$ machinectl status debian-tree
$ machinectl reboot debian-tree
$ machinectl poweroff debian-tree
Note that these are analogous to
$ systemctl reboot
$ systemctl poweroff
which we use for managing our systemd (host) servers
* But all this has to be on our local machine, right?
- Nope.
$ machinectl -H [email protected]
$ machinectl -H [email protected]:debian-tree
* Daemons, services, and units
* Daemonizing, the old way:
- Write a shell script
- Implementing each target
- Which executes sequentially with others
- Make sure your program remembers to fork twice, not just once!
- Oh, but hopefully it didn't call setuid
- Which file is the PID written in again?
- But wait, did the PID get reused?
All in all, it requires [[http://www.netzmafia.de/skripten/unix/linux-daemon-howto.html][fifteen different steps]], with serious consequences for even small mistakes
* Really?
- Yes, and that's just for one daemon.
- Also, "Process monitoring? What's that?"
* Daemonizing, the new way:
- Write a single `.service` file for your program.
[Service]
ExecStart=/usr/bin/foobard
[Install]
WantedBy=multi-user.target
No fork. No pain.
* Daemonizing containers
$ mv ~/debian-tree /var/lib/container/debian-tree
$ systemctl start [email protected] # start now
$ systemctl enable [email protected] # autostart on boot
* How do we get logs?
- Easy. On the host, we normally view logs by executing:
$ journalctl
- If we have a container running on the host, we can do:
$ journalctl -M debian-tree
* What about profiling?
Same thing.
$ systemd-analyze -M debian-tree # list startup time
$ systemd-analyze blame -M debian-tree # break down the boot time per-unit
* But what about networking?
* Networking just works
- The defaults are probably what you want
- But you can also configure specific network interfaces, network bridges, `macvlan`, and more
- Docker doesn't let you do this (...or so a lot of people *think*!)
* How can I control resources for a container?
$ systemd-cgroup
*cgroups* (control groups) are a kernel feature for managing resources for a single process or collection of processes, such as:
- Limiting memory/CPU usage
- Limiting I/O access
- Prioritizing important tasks over others
- etc.
* Is this all specific to systemd, or can I use Docker?
.image porquenolosdos.png
$ systemd-nspawn --machine bashtest --directory ~/bashtestcontainer /bin/bash
or even:
$ machinectl pull-dkr chimeracoder/nginx-nspawn --dkr-index-url https://index.docker.io
* Wait.
_what?!_
* Remember what we said at the beginning
- _At_its_core,_your_OS_is_just_a_bunch_of_files_
- _Along_with_an_ /sbin/init _file_
- _Different_distributions_distribute_different_files_
- _That's_basically_it._
Containers let you virtualize *parts* of your OS, without requiring you to virtualize the *whole* OS.
Containers let you virtualize the filesystem, the process tree, the network stack,`/proc`, `/sys`, and more *selectively*.
* So why use Docker at all?
- For many use cases, it may not matter one way or the other
- Docker is not the only containerization tool around, but it is probably the most popular
- Docker has a healthy ecosystem (the container equivalent of "package support")
- Try it yourself both ways. As you can see, it's easy to switch back and forth
* Try it yourself!
Some cool things you can do with systemd-nspawn:
- "Execute this command on my root filesystem, but roll back any changes at the end"
- "Run nginx inside its own container on boot, but limit it to 512 MB of RAM and 200% CPU"
- "Give me a container that has its own private network and its own IP and MAC addresses, but map certain ports on the host to the container"
- "Run this container with its own daemons in it, and monitor them to make sure they don't fail"
- "Download this container from the Docker Hub and run it every time I boot, but without installing Docker"