mirror of
https://github.com/linuxkit/linuxkit.git
synced 2025-07-19 09:16:29 +00:00
Merge pull request #1961 from deitch/compose-examples
add compose dynamic
This commit is contained in:
commit
982bddb185
2
projects/compose/.gitignore
vendored
Normal file
2
projects/compose/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
image-cache/
|
||||
dist/
|
49
projects/compose/Makefile
Normal file
49
projects/compose/Makefile
Normal file
@ -0,0 +1,49 @@
|
||||
.PHONY: tag push hash dynamic static cache-images run-static run-dynamic
|
||||
|
||||
ORG?=linuxkitprojects
|
||||
IMAGE=compose
|
||||
DEPS=image/Dockerfile docker-compose.yml image/waitfordocker.sh image/load-images-and-compose.sh
|
||||
COMMON_IMAGES := \
|
||||
nginx:alpine \
|
||||
traefik
|
||||
|
||||
|
||||
HASH?=$(shell git ls-tree HEAD -- ./image | awk '{print $$3}')
|
||||
|
||||
hash:
|
||||
@echo ${HASH}
|
||||
|
||||
tag: $(DEPS)
|
||||
docker build --squash --no-cache -t $(ORG)/$(IMAGE):$(HASH) image/
|
||||
|
||||
push: tag
|
||||
DOCKER_CONTENT_TRUST=1 docker pull $(ORG)/$(IMAGE):$(HASH) || \
|
||||
DOCKER_CONTENT_TRUST=1 docker push $(ORG)/$(IMAGE):$(HASH)
|
||||
|
||||
dynamic:
|
||||
mkdir -p dist
|
||||
moby build -name compose-dynamic -dir dist/ compose-dynamic.yml
|
||||
|
||||
static: cache-images
|
||||
mkdir -p dist
|
||||
moby build -name compose-static -dir dist/ compose-static.yml
|
||||
|
||||
run-dynamic:
|
||||
linuxkit run dist/compose-dynamic
|
||||
|
||||
run-static:
|
||||
linuxkit run dist/compose-static
|
||||
|
||||
clean:
|
||||
rm -rf image-cache
|
||||
|
||||
image-cache/%.tar:
|
||||
mkdir -p $(dir $@)
|
||||
DOCKER_CONTENT_TRUST=1 docker image pull $(shell basename $@ .tar)
|
||||
docker image save -o $@ $(shell basename $@ .tar)
|
||||
|
||||
# use make here for each image rather than a single for loop so we can cache dependencies
|
||||
cache-images:
|
||||
for image in $(COMMON_IMAGES) ; do \
|
||||
make "image-cache/$${image}.tar" ; \
|
||||
done
|
57
projects/compose/README.md
Normal file
57
projects/compose/README.md
Normal file
@ -0,0 +1,57 @@
|
||||
# Compose Project
|
||||
|
||||
The purpose of this project is to show how moby and linuxkit can be used to build a runnable linuxkit image with compose-style apps ready-to-run.
|
||||
|
||||
The apps are simple:
|
||||
|
||||
* nginx serving app A
|
||||
* nginx serving app B
|
||||
* traefik routing on the basis of hostname between apps A and B
|
||||
|
||||
|
||||
## Compose Methods
|
||||
We provide samples of two methods for using compose: dynamic and static.
|
||||
|
||||
Both methods use the image `linuxkit/compose`. The image does the following:
|
||||
|
||||
1. Wait for compose to be ready.
|
||||
2. If there are any tar files available in `/images/*.tar`, treat them as tarred up docker images and load them into docker via `docker load ...`
|
||||
3. Run `docker compose ...`
|
||||
|
||||
The only difference between dynamic and static is whether or not container images are pre-loaded in the linuxkit image.
|
||||
|
||||
* Compose: the `linuxkit/compose` image looks for a compose file at `/compose/docker-compose.yml`
|
||||
* Images: the `linuxkit/compose` image looks for tarred container images at `/compose/images/*.tar`
|
||||
|
||||
### Dynamic
|
||||
Dynamic loads the _compose_ config into the linuxkit image at build time. Container images are not pre-loaded, and thus docker loads the container images from the registry **at run-time**. This is no different than doing the following:
|
||||
|
||||
1. Using the docker linuxkit image
|
||||
2. Connecting remotely via the docker API
|
||||
3. Running the compose file remotely
|
||||
|
||||
Except that the compose is run at launch time, and there is no need for a remote connection to the docker API.
|
||||
|
||||
It works by loading the `docker-compose.yml` file onto the linuxkit image, and making it available to the `compose` container image via a bind-mount.
|
||||
|
||||
To build a dynamic image, do `make dynamic`. To run it, do `make run-dynamic`.
|
||||
|
||||
### Static
|
||||
Static loads the _compose_ config **and** the container _images_ into the linuxkit image at build time. When run, docker loads the images from its local cache and does not depend on access to a registry.
|
||||
|
||||
It works by loading the `docker-compose.yml` file onto the linuxkit image and tarred up container image files. It then makes them available to the `compose` container image via bind-mounts.
|
||||
|
||||
|
||||
To build a static image, do `make static`. To run it, do `make run-static`.
|
||||
|
||||
Static images pre-load them by doing:
|
||||
|
||||
1. Download the image locally `docker image pull <image>`
|
||||
2. Save the image to a local tar file `docker image save -o <image> <imagename>.tar`
|
||||
3. copy the tar file to the container image
|
||||
4. When starting the container from the image with the files, load the images into docker before running compose: `docker image load -i <image> && rm -f <imagename>.tar`
|
||||
|
||||
### Conversion
|
||||
A final option would be converting all of the containers defined in a `docker-compose.yml` into linuxkit `services`. It also would require setting up appropriate networks and other services provided by docker when running compose.
|
||||
|
||||
An example may be added in the future.
|
56
projects/compose/compose-dynamic.yml
Normal file
56
projects/compose/compose-dynamic.yml
Normal file
@ -0,0 +1,56 @@
|
||||
kernel:
|
||||
image: "linuxkit/kernel:4.9.x"
|
||||
cmdline: "console=ttyS0 page_poison=1"
|
||||
init:
|
||||
- linuxkit/init:1b8a7e394d2ec2f1fdb4d67645829d1b5bdca037
|
||||
- linuxkit/runc:3a4e6cbf15470f62501b019b55e1caac5ee7689f
|
||||
- linuxkit/containerd:b1766e4c4c09f63ac4925a6e4612852a93f7e73b
|
||||
- linuxkit/ca-certificates:75cf419fb58770884c3464eb687ec8dfc704169d
|
||||
onboot:
|
||||
- name: sysctl
|
||||
image: "linuxkit/sysctl:3aa6bc663c2849ef239be7d941d3eaf3e6fcc018"
|
||||
- name: sysfs
|
||||
image: linuxkit/sysfs:1244c5a86dfa2318c4e304af68d37e12367e1b7f
|
||||
- name: dhcpcd
|
||||
image: "linuxkit/dhcpcd:7d2b8aaaf20c24ad7d11a5ea2ea5b4a80dc966f1"
|
||||
command: ["/sbin/dhcpcd", "--nobackground", "-f", "/dhcpcd.conf", "-1"]
|
||||
- name: binfmt
|
||||
image: "linuxkit/binfmt:8ac5535f57f0c6f5fe88317b9d22a7677093c765"
|
||||
- name: format
|
||||
image: "linuxkit/format:180cb2dc1de5e60373385080f8148abf10a3afac"
|
||||
- name: mount
|
||||
image: "linuxkit/mount:ff5338822f20375b8913f5a80f9ed4f6ea9a592b"
|
||||
command: ["/mount.sh", "/var/lib/docker"]
|
||||
services:
|
||||
- name: rngd
|
||||
image: "linuxkit/rngd:1fa4de44c961bb5075647181891a3e7e7ba51c31"
|
||||
- name: ntpd
|
||||
image: "linuxkit/openntpd:45deeb05f736162d941c9bf494983f655ab80aa5"
|
||||
- name: docker
|
||||
image: "linuxkit/docker-ce:668d62da6e3da081a8f8aca7db3e2a98adf5da59"
|
||||
capabilities:
|
||||
- all
|
||||
net: host
|
||||
mounts:
|
||||
- type: cgroup
|
||||
options: ["rw","nosuid","noexec","nodev","relatime"]
|
||||
binds:
|
||||
- /var/lib/docker:/var/lib/docker
|
||||
- /lib/modules:/lib/modules
|
||||
- /var/run:/var/run
|
||||
- /var/html:/var/html
|
||||
- name: compose
|
||||
image: "linuxkitprojects/compose:0535e78608f57702745dfd56fbe78d28d237e469"
|
||||
binds:
|
||||
- /var/run:/var/run
|
||||
- /var/compose:/compose
|
||||
files:
|
||||
- path: var/html/a/index.html
|
||||
source: html-a.html
|
||||
- path: var/html/b/index.html
|
||||
source: html-b.html
|
||||
- path: var/compose/docker-compose.yml
|
||||
source: docker-compose.yml
|
||||
trust:
|
||||
org:
|
||||
- linuxkit
|
60
projects/compose/compose-static.yml
Normal file
60
projects/compose/compose-static.yml
Normal file
@ -0,0 +1,60 @@
|
||||
kernel:
|
||||
image: "linuxkit/kernel:4.9.x"
|
||||
cmdline: "console=ttyS0 page_poison=1"
|
||||
init:
|
||||
- linuxkit/init:1b8a7e394d2ec2f1fdb4d67645829d1b5bdca037
|
||||
- linuxkit/runc:3a4e6cbf15470f62501b019b55e1caac5ee7689f
|
||||
- linuxkit/containerd:b1766e4c4c09f63ac4925a6e4612852a93f7e73b
|
||||
- linuxkit/ca-certificates:75cf419fb58770884c3464eb687ec8dfc704169d
|
||||
onboot:
|
||||
- name: sysctl
|
||||
image: "linuxkit/sysctl:3aa6bc663c2849ef239be7d941d3eaf3e6fcc018"
|
||||
- name: sysfs
|
||||
image: linuxkit/sysfs:1244c5a86dfa2318c4e304af68d37e12367e1b7f
|
||||
- name: dhcpcd
|
||||
image: "linuxkit/dhcpcd:7d2b8aaaf20c24ad7d11a5ea2ea5b4a80dc966f1"
|
||||
command: ["/sbin/dhcpcd", "--nobackground", "-f", "/dhcpcd.conf", "-1"]
|
||||
- name: binfmt
|
||||
image: "linuxkit/binfmt:8ac5535f57f0c6f5fe88317b9d22a7677093c765"
|
||||
- name: format
|
||||
image: "linuxkit/format:180cb2dc1de5e60373385080f8148abf10a3afac"
|
||||
- name: mount
|
||||
image: "linuxkit/mount:ff5338822f20375b8913f5a80f9ed4f6ea9a592b"
|
||||
command: ["/mount.sh", "/var/lib/docker"]
|
||||
services:
|
||||
- name: rngd
|
||||
image: "linuxkit/rngd:1fa4de44c961bb5075647181891a3e7e7ba51c31"
|
||||
- name: ntpd
|
||||
image: "linuxkit/openntpd:45deeb05f736162d941c9bf494983f655ab80aa5"
|
||||
- name: docker
|
||||
image: "linuxkit/docker-ce:668d62da6e3da081a8f8aca7db3e2a98adf5da59"
|
||||
capabilities:
|
||||
- all
|
||||
net: host
|
||||
mounts:
|
||||
- type: cgroup
|
||||
options: ["rw","nosuid","noexec","nodev","relatime"]
|
||||
binds:
|
||||
- /var/lib/docker:/var/lib/docker
|
||||
- /lib/modules:/lib/modules
|
||||
- /var/run:/var/run
|
||||
- /var/html:/var/html
|
||||
- name: compose
|
||||
image: "linuxkitprojects/compose:0535e78608f57702745dfd56fbe78d28d237e469"
|
||||
binds:
|
||||
- /var/run:/var/run
|
||||
- /var/compose:/compose
|
||||
files:
|
||||
- path: var/html/a/index.html
|
||||
source: html-a.html
|
||||
- path: var/html/b/index.html
|
||||
source: html-b.html
|
||||
- path: var/compose/docker-compose.yml
|
||||
source: docker-compose.yml
|
||||
- path: var/compose/images/nginx:alpine.tar
|
||||
source: image-cache/nginx:alpine.tar
|
||||
- path: var/compose/images/traefik.tar
|
||||
source: image-cache/traefik.tar
|
||||
trust:
|
||||
org:
|
||||
- linuxkit
|
25
projects/compose/docker-compose.yml
Normal file
25
projects/compose/docker-compose.yml
Normal file
@ -0,0 +1,25 @@
|
||||
version: '2.1'
|
||||
services:
|
||||
a:
|
||||
image: nginx:alpine
|
||||
volumes:
|
||||
- /var/html/a:/usr/share/nginx/html
|
||||
labels:
|
||||
- "traefik.backend=a"
|
||||
- "traefik.frontend.rule=Host:a.docker.localhost"
|
||||
b:
|
||||
image: nginx:alpine
|
||||
volumes:
|
||||
- /var/html/b:/usr/share/nginx/html
|
||||
labels:
|
||||
- "traefik.backend=b"
|
||||
- "traefik.frontend.rule=Host:b.docker.localhost"
|
||||
- "traefik.port=80"
|
||||
proxy:
|
||||
image: traefik
|
||||
command: --web --docker --docker.domain=docker.localhost --logLevel=DEBUG
|
||||
ports:
|
||||
- "80:80"
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- /dev/null:/traefik.toml
|
8
projects/compose/html-a.html
Normal file
8
projects/compose/html-a.html
Normal file
@ -0,0 +1,8 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>A index</title>
|
||||
</head>
|
||||
<body>
|
||||
This is the index for A
|
||||
</body>
|
||||
</html>
|
8
projects/compose/html-b.html
Normal file
8
projects/compose/html-b.html
Normal file
@ -0,0 +1,8 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>B index</title>
|
||||
</head>
|
||||
<body>
|
||||
This is the index for B
|
||||
</body>
|
||||
</html>
|
27
projects/compose/image/Dockerfile
Normal file
27
projects/compose/image/Dockerfile
Normal file
@ -0,0 +1,27 @@
|
||||
FROM docker/compose:1.13.0
|
||||
# because compose requires all sorts of dynamic libs, including glibc, it is much easier to
|
||||
# add docker client to compose than the reverse
|
||||
|
||||
ENV DOCKER_BUCKET get.docker.com
|
||||
ENV DOCKER_VERSION 17.05.0-ce
|
||||
ENV DOCKER_SHA256 340e0b5a009ba70e1b644136b94d13824db0aeb52e09071410f35a95d94316d9
|
||||
|
||||
# we need docker compose and docker load
|
||||
# also need curl to test availability of docker API
|
||||
RUN apk add --update curl
|
||||
|
||||
# we only need the client
|
||||
RUN set -x \
|
||||
&& curl -fSL "https://${DOCKER_BUCKET}/builds/Linux/x86_64/docker-${DOCKER_VERSION}.tgz" -o docker.tgz \
|
||||
&& echo "${DOCKER_SHA256} *docker.tgz" | sha256sum -c - \
|
||||
&& tar -xzvf docker.tgz \
|
||||
&& mv docker/docker /usr/bin/ \
|
||||
&& rm -rf docker docker.tgz \
|
||||
&& docker -v
|
||||
|
||||
|
||||
RUN mkdir -p /compose /app
|
||||
WORKDIR /app
|
||||
COPY . /app
|
||||
ENTRYPOINT ["/app/waitfordocker.sh"]
|
||||
CMD ["/app/load-images-and-compose.sh"]
|
17
projects/compose/image/load-images-and-compose.sh
Executable file
17
projects/compose/image/load-images-and-compose.sh
Executable file
@ -0,0 +1,17 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
#########
|
||||
#
|
||||
# load any cached mounted images, and run compose
|
||||
#
|
||||
########
|
||||
|
||||
[ -n "$DEBUG" ] && set -x
|
||||
|
||||
for image in /compose/images/*.tar ; do
|
||||
docker image load -i $image && rm -f $image
|
||||
done
|
||||
|
||||
|
||||
docker-compose -f /compose/docker-compose.yml up -d
|
47
projects/compose/image/waitfordocker.sh
Executable file
47
projects/compose/image/waitfordocker.sh
Executable file
@ -0,0 +1,47 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
#########
|
||||
#
|
||||
# wait for docker socket to be ready, then run the rest of the command
|
||||
#
|
||||
########
|
||||
RETRIES=${RETRIES:-"-1"}
|
||||
WAIT=${WAIT:=10}
|
||||
[ -n "$DEBUG" ] && set -x
|
||||
|
||||
# keep retrying until docker is ready or we hit our limut
|
||||
retry_or_fail() {
|
||||
local retry_count=0
|
||||
local success=1
|
||||
local cmd=$1
|
||||
local retryMax=$2
|
||||
local retrySleep=$3
|
||||
local message=$4
|
||||
until [[ $retry_count -ge $retryMax && $retryMax -ne -1 ]]; do
|
||||
echo "trying to $message"
|
||||
set +e
|
||||
$cmd
|
||||
success=$?
|
||||
set -e
|
||||
[[ $success == 0 ]] && break
|
||||
retry_count=$(( $retry_count+1 )) || true
|
||||
echo "attempt number $retry_count failed to $message, sleeping $retrySleep seconds..."
|
||||
sleep $retrySleep
|
||||
done
|
||||
# did we succeed?
|
||||
if [[ $success != 0 ]]; then
|
||||
echo "failed to $message after $retryMax tries. Exiting..." >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
connect_to_docker() {
|
||||
[ -S /var/run/docker.sock ] || return 1
|
||||
curl --unix-socket /var/run/docker.sock http://localhost/containers/json >/dev/null 2>&1 || return 1
|
||||
}
|
||||
# try to connect to docker
|
||||
retry_or_fail connect_to_docker $RETRIES $WAIT "connect to docker"
|
||||
|
||||
# if we got here, we succeeded
|
||||
$@
|
Loading…
Reference in New Issue
Block a user