├── .gitignore ├── Dockerfile ├── README.md ├── build.sh ├── container ├── Makefile ├── include │ └── main.h └── src │ └── main.c ├── demo.gif └── run.sh /.gitignore: -------------------------------------------------------------------------------- 1 | *.gz -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine 2 | COPY ./container /home 3 | WORKDIR /home 4 | RUN apk add build-base 5 | RUN apk add sudo 6 | RUN cd /home 7 | RUN sudo tar -zxf rootfs.tar.gz 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # What is it ? 2 | 3 | ![docker_logo](https://avatars0.githubusercontent.com/u/5429470?s=200&v=4) 4 | 5 | Hi! I'm a big fan of Docker and I always wanted to know how it worked under the box. So the best way to understand is by practice, this is why I decided to create my own little linux container. 6 | You will see that we can create a simple isolated process with his own root filesystem and his own namespaces with only some lines of code :D 7 | 8 | ![demo](https://raw.githubusercontent.com/NastyZ98/c_container/master/demo.gif) 9 | 10 | # How it work ? 11 | I started by create a child process using clone() with new namespaces, next I changed the root directory by giving a new rootfs (e.g: '/home/rootfs' in my case) and changed the actual directory by the root directory (e.g: '/'). 12 | 13 | # How to use ? 14 | Because I work on macOS I use Docker to test my "container". Yes containerception. 15 | 16 | BEFORE ALL DOWNLOAD THE ROOT FILESYSTEM: 17 | 18 | `cd ./container && wget https://github.com/ericchiang/containers-from-scratch/releases/download/v0.1.0/rootfs.tar.gz` 19 | 20 | Just run `./build.sh` and continue with `./run.sh` 21 | It will create a container based on my Dockerfile and will copy the "container" folder containing sources and a compressed rootfs, next the archive will be decompressed into the container allowing you make and execute my program, thanks to `make`. 22 | 23 | - ./build.sh 24 | - ./run.sh 25 | - make 26 | - ./container 27 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | docker build -t my_container ./ -------------------------------------------------------------------------------- /container/Makefile: -------------------------------------------------------------------------------- 1 | SRCS = src/main.c 2 | 3 | OBJS = $(SRCS:.c=.o) 4 | 5 | CC = gcc 6 | 7 | CFLAGS = -W -Wextra -Wall -Werror -I./include 8 | 9 | NAME = container 10 | 11 | all: $(OBJS) 12 | $(CC) -o $(NAME) $(OBJS) 13 | 14 | clean: 15 | rm -f $(OBJS) 16 | 17 | fclean: clean 18 | rm -f $(NAME) 19 | 20 | re: fclean all 21 | 22 | .PHONY: clean fclean re -------------------------------------------------------------------------------- /container/include/main.h: -------------------------------------------------------------------------------- 1 | #ifndef MAIN_H_ 2 | #define MAIN_H_ 3 | #define _GNU_SOURCE 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | int create_container(void); 16 | int child(void *args); 17 | 18 | #endif -------------------------------------------------------------------------------- /container/src/main.c: -------------------------------------------------------------------------------- 1 | #include "main.h" 2 | 3 | int main(void) 4 | { 5 | int namespaces = CLONE_NEWUTS | CLONE_NEWPID | CLONE_NEWIPC | CLONE_NEWNS | CLONE_NEWNET; 6 | pid_t container; 7 | 8 | container = clone(child, malloc(4096) + 4096, SIGCHLD | namespaces, NULL); 9 | if (container == -1) { 10 | perror("clone"); 11 | exit(1); 12 | } 13 | waitpid(container, NULL, 0); 14 | return 0; 15 | } 16 | 17 | int create_container(void) 18 | { 19 | char *cmd[] = { "/bin/bash", NULL }; 20 | 21 | chroot("/home/rootfs"); 22 | chdir("/"); 23 | mount("proc", "proc", "proc", 0, ""); 24 | execv("/bin/bash", cmd); 25 | perror("exec"); 26 | exit(EXIT_FAILURE); 27 | } 28 | 29 | int child(void *args) 30 | { 31 | (void)args; 32 | create_container(); 33 | return (0); 34 | } -------------------------------------------------------------------------------- /demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nathanagez/c_container/3126dc9c4a9cf39e5e51f18a6e24ab589bd0bec3/demo.gif -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | docker container run -ti --privileged my_container --------------------------------------------------------------------------------