shocker

Docker implemented in around 300 lines of bash ⚡️

View on GitHub

shocker

Docker implemented in around 300 lines of bash ⚡️

Fork of bocker (github.com/p8952/bocker). updated for 2026.

Prerequisites

The following packages are needed to run shocker.

Additionally your system will need to be configured with the following:

Even if you meet the above prerequisites you probably still want to run shocker in a virtual machine. shocker runs as root and among other things needs to make changes to your network interfaces, routing table, and firewall rules. I can make no guarantees that it won’t trash your system.

Example Usage

> shocker pull alpine
Pulling layer 6a0ac1617861a677b04…
Created: img_aa090

> shocker images
IMAGE_ID		SOURCE
img_aa090		alpine:latest

> shocker run img_aa090 cat /etc/issue
Welcome to Alpine Linux 3.23
Kernel \r on \m (\l)

> shocker ps
CONTAINER_ID		COMMAND
ps_58122		cat /etc/issue

> shocker logs ps_58122
Welcome to Alpine Linux 3.23
Kernel \r on \m (\l)

> shocker rm ps_58122
Removed: ps_58122

> shocker run --rm img_aa090 curl
/bin/sh: curl: not found
Removed: ps_c3037

> shocker run img_0c690 apk add curl
(1/9) Installing brotli-libs (1.2.0-r0)
(2/9) Installing c-ares (1.34.6-r0)
(3/9) Installing libunistring (1.4.1-r0)
(4/9) Installing libidn2 (2.3.8-r0)
(5/9) Installing nghttp2-libs (1.69.0-r0)
(6/9) Installing libpsl (0.21.5-r3)
(7/9) Installing zstd-libs (1.5.7-r2)
(8/9) Installing libcurl (8.19.0-r0)
(9/9) Installing curl (8.19.0-r0)
Executing busybox-1.37.0-r30.trigger
OK: 13.0 MiB in 25 packages

> shocker ps
CONTAINER_ID		COMMAND
ps_19998		apk add curl

> shocker commit ps_19998 img_0c690
Removed: img_0c690
Created: img_0c690

> shocker run --rm img_0c690 which curl
/usr/bin/curl
Removed: ps_42f9f

> shocker run --rm -it img_0c690
/ # ls
bin           etc           img.source    media         opt           ps_19998.cmd  ps_ab245.cmd  run           srv           tmp           var
dev           home          lib           mnt           proc          ps_19998.log  root          sbin          sys           usr
/ # date
Fri May 22 23:54:38 UTC 2026
/ # exit
Removed: ps_9c548

Functionality: Currently Implemented

shocker init provides a very limited implementation of docker build

2026 Modernization

What broke in bocker and what shocker fixes

Second pass of fixes/improvements

Third pass of fixes

Fourth pass of fixes/improvements

Fifth pass of fixes/improvements

Things that still require the same host setup as bocker

btrfs /var/shocker setup

# 1. Install btrfs tools if needed
apt install -y btrfs-progs   # Debian/Ubuntu

# 2. Create a sparse 10G image file (sparse = no real disk used until written)
truncate -s 10G /var/shocker.img

# 3. Format it
mkfs.btrfs /var/shocker.img

# 4. Mount it
mkdir -p /var/shocker
mount -o loop /var/shocker.img /var/shocker

# 5. Persist across reboots
echo '/var/shocker.img /var/shocker btrfs loop 0 0' >> /etc/fstab

proxy

If your setup requires a http proxy to access docker hub (etc.) you can set that up esp. for the shocker pull like this:

SHOCKER_REGISTRY=example.com:8080 shocker pull alpine

Functionality: Not Yet Implemented

License

Copyright (C) 2015 Peter Wilmott Copyright (C) 2026 Tracey Jaquith

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Understanding containers from scratch

curious to run just chroot?

# setup a chroot dir (*everything* has to get copied in)
mkdir /tmp/myimg
echo hello > /tmp/myimg/hello.txt

# see what shared libs each binary needs (linux-vdso is virtual — kernel provides it, no file to copy)
BINS=(/bin/sh /bin/cat /bin/echo)
for b in "${BINS[@]}"; do ldd "$b"; done

# mirror each lib's directory structure into the chroot, then copy
for b in "${BINS[@]}"; do ldd "$b" | grep -Eo '/[^ ]+'; done | sort -u | \
while IFS= read -r lib; do
  mkdir -p "/tmp/myimg$(dirname "$lib")"
  cp "$lib" "/tmp/myimg$lib"
done

# copy the binaries themselves
mkdir -p /tmp/myimg/bin
cp "${BINS[@]}" /tmp/myimg/bin/

# mount proc so the shell isn't blind, then drop in
mkdir -p /tmp/myimg/proc
mount -t proc proc /tmp/myimg/proc
chroot /tmp/myimg /bin/sh
# exit to leave

# cleanup
umount /tmp/myimg/proc

example run:

...
chroot /tmp/myimg /bin/sh
mount: (hint) your fstab has been modified, but systemd still uses
       the old version; use 'systemctl daemon-reload' to reload.
# cat hello.txt
hello
# echo hai
hai
# exit

example layout:

find /tmp/myimg -type f |sort
/tmp/myimg/bin/cat
/tmp/myimg/bin/echo
/tmp/myimg/bin/sh
/tmp/myimg/hello.txt
/tmp/myimg/lib64/ld-linux-x86-64.so.2
/tmp/myimg/lib/x86_64-linux-gnu/libc.so.6

direct chroot into a shocker image

this will have file/dir isolation, but not process isolation (eg: ps aux shows host processes)

# pick some shocker image you have pulled and update this line:
IMG=/var/shocker/img_0a690
mount -t proc proc $IMG/proc
chroot $IMG /bin/sh
# play around ^, exit, then cleanup:
umount $IMG/proc