From a3883938bc773221c74b0ea9f974ba58e8bed560 Mon Sep 17 00:00:00 2001 From: Mikhail Gordeev Date: Sat, 11 Jun 2022 01:19:22 +0300 Subject: [PATCH] Initial commit --- .gitignore | 1 + build.py | 260 +++++++++++++++++++++++++++++ images/apache2/Dockerfile.template | 13 ++ images/apache2/README.md | 13 ++ images/base/Dockerfile.template | 11 ++ images/base/README.md | 4 + images/devel/Dockerfile.template | 61 +++++++ images/devel/README.md | 15 ++ images/etcd/Dockerfile.template | 13 ++ images/etcd/README.md | 13 ++ images/gitea/Dockerfile.template | 31 ++++ images/gitea/README.md | 22 +++ images/gitea/app.ini | 15 ++ images/gitea/entrypoint.sh | 34 ++++ images/nginx/Dockerfile.template | 18 ++ images/nginx/README.md | 13 ++ images/python/Dockerfile.template | 15 ++ images/python/README.md | 13 ++ images/ruby/Dockerfile.template | 11 ++ images/ruby/README.md | 10 ++ images/systemd/Dockerfile.template | 24 +++ images/systemd/README.md | 10 ++ 22 files changed, 620 insertions(+) create mode 100644 .gitignore create mode 100755 build.py create mode 100644 images/apache2/Dockerfile.template create mode 100644 images/apache2/README.md create mode 100644 images/base/Dockerfile.template create mode 100644 images/base/README.md create mode 100644 images/devel/Dockerfile.template create mode 100644 images/devel/README.md create mode 100644 images/etcd/Dockerfile.template create mode 100644 images/etcd/README.md create mode 100644 images/gitea/Dockerfile.template create mode 100644 images/gitea/README.md create mode 100644 images/gitea/app.ini create mode 100755 images/gitea/entrypoint.sh create mode 100644 images/nginx/Dockerfile.template create mode 100644 images/nginx/README.md create mode 100644 images/python/Dockerfile.template create mode 100644 images/python/README.md create mode 100644 images/ruby/Dockerfile.template create mode 100644 images/ruby/README.md create mode 100644 images/systemd/Dockerfile.template create mode 100644 images/systemd/README.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9414382 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +Dockerfile diff --git a/build.py b/build.py new file mode 100755 index 0000000..d045335 --- /dev/null +++ b/build.py @@ -0,0 +1,260 @@ +#!/usr/bin/python3 + +import argparse +import os +import re +import subprocess +from graphlib import TopologicalSorter +from pathlib import Path + +from jinja2 import Template + + +IMAGES_DIR = Path("images") + + +class DockerBuilder: + def make_from_re(self): + registry = r"(?P[\w.:]+)" + organization = r"(?P\w+)" + name = r"(?P\w+)" + tag = r"(?P[\w.]+)" + return f"^FROM (:?{registry}/)?(:?{organization}/)?{name}(:?:{tag})?$" + + def __init__(self, registry, organization, latest, dry_run): + self.from_re = re.compile(self.make_from_re()) + self.images_dir = IMAGES_DIR + self.registry = registry + self.organization = organization + self.latest = latest + self.dry_run = dry_run + + def forall_images(consume_result): + def forall_images_decorator(f): + def wrapped(self, *args, **kwargs): + for image in self.images_dir.iterdir(): + local_kwargs = { + "image": image, + "dockerfile": image / "Dockerfile", + "dockerfile_template": image / "Dockerfile.template", + } + new_kwargs = kwargs | local_kwargs + yield f(self, *args, **new_kwargs) + + def consumer(*args, **kwargs): + for _ in wrapped(*args, **kwargs): + pass + + if consume_result: + return consumer + else: + return wrapped + + return forall_images_decorator + + @forall_images(consume_result=True) + def remove_dockerfiles(self, **kwargs): + if kwargs["dockerfile"].exists(): + kwargs["dockerfile"].unlink() + + @forall_images(consume_result=True) + def render_dockerfiles(self, branch, **kwargs): + if kwargs["dockerfile_template"].exists(): + if self.registry: + registry = self.registry.rstrip("/") + "/" + alt_image = "alt/alt" + else: + registry = "" + alt_image = "alt" + rendered = Template(kwargs["dockerfile_template"].read_text()).render( + alt_image=alt_image, + branch=branch, + organization=self.organization, + registry=registry, + ) + kwargs["dockerfile"].write_text(rendered + "\n") + + @forall_images(consume_result=False) + def get_requires(self, **kwargs): + requires = set() + + for line in kwargs["dockerfile"].read_text().splitlines(): + if match := re.match(self.from_re, line): + from_image = match.groupdict() + if from_image["organization"] == self.organization: + requires.add(from_image["name"]) + + return (kwargs["image"].name, requires) + + def get_build_order(self): + requires = {} + for image, image_requires in self.get_requires(): + requires[image] = image_requires + ts = TopologicalSorter(requires) + return ts.static_order() + + def render_full_tag(self, image, tag): + if self.registry: + registry = self.registry.rstrip("/") + "/" + else: + registry = "" + if tag: + tag = f":{tag}" + return f"{registry}{self.organization}/{image}{tag}" + + def run(self, cmd, *args, **kwargs): + if self.dry_run: + pre_cmd = ["echo"] + else: + pre_cmd = [] + subprocess.run(pre_cmd + cmd, *args, **kwargs) + + def build(self, image, arches, tag): + new_env = os.environ | {"DOCKER_BUILDKIT": "1"} + + platforms = ",".join([f"linux/{a}" for a in arches]) + full_name = self.render_full_tag(image, tag) + if tag == self.latest: + lates_name = self.render_full_tag(image, "latest") + names = f"{full_name},{lates_name}" + else: + names = full_name + + cmd = [ + "buildctl", + "build", + "--frontend=dockerfile.v0", + "--local", + "context=.", + "--local", + "dockerfile=.", + "--opt", + f"platform={platforms}", + "--output", + f'type=image,"name={names}",push=true', + ] + self.run( + cmd, + cwd=self.images_dir / image, + env=new_env, + ) + + +def parse_args(): + stages = ["build", "remove_dockerfiles", "render_dockerfiles", "push"] + arches = ["amd64", "386", "arm64", "arm", "ppc64le"] + branches = ["p9", "p10", "sisyphus"] + images = os.listdir(IMAGES_DIR) + + parser = argparse.ArgumentParser( + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + ) + parser.add_argument( + "-r", + "--registry", + default="registry.altlinux.org", + ) + parser.add_argument( + "-o", + "--organization", + default="alt", + ) + parser.add_argument( + "-l", + "--latest", + default="p10", + ) + parser.add_argument( + "--dry-run", + action="store_true", + help="print instead of running docker commands", + ) + parser.add_argument( + "-i", + "--images", + nargs="+", + default=images, + choices=images, + help="list of branches", + ) + parser.add_argument( + "--skip-images", + nargs="+", + default=[], + choices=images, + help="list of skipping images", + ) + parser.add_argument( + "-a", + "--arches", + nargs="+", + default=arches, + choices=arches, + help="list of arches", + ) + parser.add_argument( + "--skip-arches", + nargs="+", + default=[], + choices=arches, + help="list of skipping arches", + ) + parser.add_argument( + "-b", + "--branches", + nargs="+", + default=branches, + choices=branches, + help="list of branches", + ) + parser.add_argument( + "--skip-branches", + nargs="+", + default=[], + choices=branches, + help="list of skipping branches", + ) + parser.add_argument( + "--stages", + nargs="+", + default=stages, + choices=stages, + help="list of stages", + ) + parser.add_argument( + "--skip-stages", + nargs="+", + default=[], + choices=stages, + help="list of skipping stages", + ) + args = parser.parse_args() + + args.stages = set(args.stages) - set(args.skip_stages) + args.branches = set(args.branches) - set(args.skip_branches) + args.images = set(args.images) - set(args.skip_images) + + return args + + +def main(): + args = parse_args() + for branch in args.branches: + db = DockerBuilder(args.registry, args.organization, args.latest, args.dry_run) + if "remove_dockerfiles" in args.stages: + db.remove_dockerfiles() + if "render_dockerfiles" in args.stages: + db.render_dockerfiles(branch) + if "build" in args.stages: + for image in db.get_build_order(): + if image not in args.images: + continue + + if "build" in args.stages: + db.build(image, args.arches, branch) + + +if __name__ == "__main__": + main() + +# vim: colorcolumn=89 diff --git a/images/apache2/Dockerfile.template b/images/apache2/Dockerfile.template new file mode 100644 index 0000000..dffe3a1 --- /dev/null +++ b/images/apache2/Dockerfile.template @@ -0,0 +1,13 @@ +FROM {{ registry }}{{ alt_image }}:{{ branch }} + +MAINTAINER alt-cloud + +RUN apt-get update && \ + apt-get install -y apache2; \ + rm -f /var/cache/apt/archives/*.rpm \ + /var/cache/apt/*.bin \ + /var/lib/apt/lists/*.* + +EXPOSE 80 + +CMD ["/usr/sbin/httpd2", "-D", "NO_DETACH", "-k", "start"] diff --git a/images/apache2/README.md b/images/apache2/README.md new file mode 100644 index 0000000..d1b9d96 --- /dev/null +++ b/images/apache2/README.md @@ -0,0 +1,13 @@ +dockerfiles-alt-apache2 +======================== + +ALT dockerfile for apache2. + +Copy Dockerfile somewhere and build the image: +`$ docker build --rm -t /apache2 .` + +And launch the apache2 container: +`docker run -p 80:80 /apache2` + +It could be test via: +`curl localhost:80` diff --git a/images/base/Dockerfile.template b/images/base/Dockerfile.template new file mode 100644 index 0000000..5fb3ac6 --- /dev/null +++ b/images/base/Dockerfile.template @@ -0,0 +1,11 @@ +FROM {{ registry }}{{ alt_image }}:{{ branch }} + +MAINTAINER alt-cloud + +RUN apt-get update && \ + apt-get install -y glibc-gconv-modules glibc-locales tzdata; \ + rm -f /var/cache/apt/archives/*.rpm \ + /var/cache/apt/*.bin \ + /var/lib/apt/lists/*.* + +CMD ["bash"] diff --git a/images/base/README.md b/images/base/README.md new file mode 100644 index 0000000..c34f978 --- /dev/null +++ b/images/base/README.md @@ -0,0 +1,4 @@ +ALT dockerfile for base image. + +The base image is contains locales and other basic, but not strongly +required packages. diff --git a/images/devel/Dockerfile.template b/images/devel/Dockerfile.template new file mode 100644 index 0000000..7b14a60 --- /dev/null +++ b/images/devel/Dockerfile.template @@ -0,0 +1,61 @@ +FROM {{ registry }}{{ organization }}/base:{{ branch }} + +MAINTAINER alt-cloud + +# install editor +RUN apt-get update && \ + apt-get install -y vim-console; \ + rm -f /var/cache/apt/archives/*.rpm \ + /var/cache/apt/*.bin \ + /var/lib/apt/lists/*.* + +# install debugging tools +RUN apt-get update && \ + apt-get install -y strace gdb; \ + rm -f /var/cache/apt/archives/*.rpm \ + /var/cache/apt/*.bin \ + /var/lib/apt/lists/*.* + +# install document viewers +RUN apt-get update && \ + apt-get install -y man; \ + rm -f /var/cache/apt/archives/*.rpm \ + /var/cache/apt/*.bin \ + /var/lib/apt/lists/*.* + +# install version control system +RUN apt-get update && \ + apt-get install -y git-core perl-Git; \ + rm -f /var/cache/apt/archives/*.rpm \ + /var/cache/apt/*.bin \ + /var/lib/apt/lists/*.* + +# install network utils +RUN apt-get update && \ + apt-get install -y curl iproute2; \ + rm -f /var/cache/apt/archives/*.rpm \ + /var/cache/apt/*.bin \ + /var/lib/apt/lists/*.* + +# install file utils +RUN apt-get update && \ + apt-get install -y lsof silver-searcher; \ + rm -f /var/cache/apt/archives/*.rpm \ + /var/cache/apt/*.bin \ + /var/lib/apt/lists/*.* + +# install shell and completions +RUN apt-get update && \ + apt-get install -y zsh zsh-completions; \ + rm -f /var/cache/apt/archives/*.rpm \ + /var/cache/apt/*.bin \ + /var/lib/apt/lists/*.* + +# install compilation utils +RUN apt-get update && \ + apt-get install -y make gcc gcc-c++; \ + rm -f /var/cache/apt/archives/*.rpm \ + /var/cache/apt/*.bin \ + /var/lib/apt/lists/*.* + +CMD ["zsh"] diff --git a/images/devel/README.md b/images/devel/README.md new file mode 100644 index 0000000..deab99b --- /dev/null +++ b/images/devel/README.md @@ -0,0 +1,15 @@ +dockerfiles-alt-devel +====================== + +ALT dockerfile for developers. + +DO NOT USE THIS IN PRODUCTION! + +This image is only for devel or testing purposes. It contains packages that +usually need for debugging or testing something. + +Copy Dockerfile somewhere and build the image: +`$ docker build --rm -t /devel .` + +And launch the devel container: +`docker run -it /devel` diff --git a/images/etcd/Dockerfile.template b/images/etcd/Dockerfile.template new file mode 100644 index 0000000..d57a81a --- /dev/null +++ b/images/etcd/Dockerfile.template @@ -0,0 +1,13 @@ +FROM {{ registry }}{{ alt_image }}:{{ branch }} + +MAINTAINER alt-cloud + +RUN apt-get update && \ + apt-get install -y etcd; \ + rm -f /var/cache/apt/archives/*.rpm \ + /var/cache/apt/*.bin \ + /var/lib/apt/lists/*.* + +VOLUME /data + +ENTRYPOINT ["/usr/sbin/etcd", "--data-dir", "/data"] diff --git a/images/etcd/README.md b/images/etcd/README.md new file mode 100644 index 0000000..f364e0e --- /dev/null +++ b/images/etcd/README.md @@ -0,0 +1,13 @@ +dockerfiles-alt-etcd +========================= + +ALT dockerfile for etcd. + +Copy Dockerfile somewhere and build the image: +`$ docker build --rm -t /etcd.` + +And launch the etcd container: +`docker run -d -v :/data /etcd` + +If etcdclt watnted it could be run via: +`docker run --entrypoint etcdctl /etcd` diff --git a/images/gitea/Dockerfile.template b/images/gitea/Dockerfile.template new file mode 100644 index 0000000..4fec836 --- /dev/null +++ b/images/gitea/Dockerfile.template @@ -0,0 +1,31 @@ +FROM {{ registry }}{{ alt_image }}:{{ branch }} + +MAINTAINER alt-cloud + +RUN apt-get update && \ + apt-get install -y gitea openssh-server; \ + rm -f /var/cache/apt/archives/*.rpm \ + /var/cache/apt/*.bin \ + /var/lib/apt/lists/*.* + +RUN apt-get update && \ + apt-get install -y gosu; \ + rm -f /var/cache/apt/archives/*.rpm \ + /var/cache/apt/*.bin \ + /var/lib/apt/lists/*.* + +ENV USER gitea +ENV HOME /var/lib/gitea +ENV GITEA_WORK_DIR /var/lib/gitea + +WORKDIR /var/lib/gitea + +COPY app.ini /etc/gitea/app.ini +COPY entrypoint.sh /entrypoint.sh + +EXPOSE 3000 +EXPOSE 2222 + +VOLUME ["/var/lib/gitea"] + +ENTRYPOINT ["/entrypoint.sh"] diff --git a/images/gitea/README.md b/images/gitea/README.md new file mode 100644 index 0000000..6f9be81 --- /dev/null +++ b/images/gitea/README.md @@ -0,0 +1,22 @@ +dockerfiles-alt-gitea +====================== + +ALT dockerfile for gitea. + +Copy Dockerfile somewhere and build the image: +`$ docker build --rm -t /gitea .` + +And launch the gitea container: +`docker run -d -p 80:3000 -p 2222:22 -v :/var/lib/gitea /gitea` + +## Configuration + +After mounting gitea_path would contain all variable gitea data. Gitea +parameters could be customized via files in gitea_path. + +Main configuration paths (relative to gitea_path): +* config -> custom/conf/app.ini; +* https certificates -> custom/https/; +* mail certificates -> custom/mailer/; +* openssh server configuration and keys -> openssh/; +* sqlite3 database -> data/gitea.db. diff --git a/images/gitea/app.ini b/images/gitea/app.ini new file mode 100644 index 0000000..f27b156 --- /dev/null +++ b/images/gitea/app.ini @@ -0,0 +1,15 @@ +APP_NAME = Gitea working in ALT container +RUN_MODE = prod + +[repository] +ROOT = repos + +[database] +DB_TYPE = sqlite3 +PATH = data/gitea.db +LOG_SQL = false + +[log] +MODE = console +BUFFER_LEN = 10000 +LEVEL = Info diff --git a/images/gitea/entrypoint.sh b/images/gitea/entrypoint.sh new file mode 100755 index 0000000..ce8def8 --- /dev/null +++ b/images/gitea/entrypoint.sh @@ -0,0 +1,34 @@ +#!/bin/sh -eu + +# Use bash to debug startup errors +if [ "${1-}" = bash ]; then + exec bash +fi + +if [ ! -f custom/conf/app.ini ]; then + mkdir -p custom/conf + cp /etc/gitea/app.ini -t custom/conf +fi + +start_sshd() { + # Store openssh config and keys in openssh directory to use them if + # container recreats + if [ -d openssh ]; then + cp -a openssh/* /etc/openssh/ + else + cp -a /etc/openssh -T openssh + fi + + # Ensure keys created and saved to openssh directory + /usr/bin/ssh-keygen -A + cp -a /etc/openssh/* -t openssh + + /usr/sbin/sshd +} + +start_sshd + +chmod 0700 . +chown gitea:gitea . -R + +exec gosu gitea /usr/bin/gitea web diff --git a/images/nginx/Dockerfile.template b/images/nginx/Dockerfile.template new file mode 100644 index 0000000..ec33abd --- /dev/null +++ b/images/nginx/Dockerfile.template @@ -0,0 +1,18 @@ +FROM {{ registry }}{{ alt_image }}:{{ branch }} + +MAINTAINER alt-cloud + +RUN apt-get update && \ + apt-get install -y nginx apache2-html tzdata; \ + rm -f /var/cache/apt/archives/*.rpm \ + /var/cache/apt/*.bin \ + /var/lib/apt/lists/*.* + +RUN cd /etc/nginx/sites-enabled.d && ln -s ../sites-available.d/default.conf . + +RUN sed -Ei 's/^([[:space:]]*listen[[:space:]]+)localhost(:80)/\10.0.0.0\2/' \ + /etc/nginx/sites-available.d/default.conf + +EXPOSE 80 + +CMD ["nginx", "-g", "daemon off;"] diff --git a/images/nginx/README.md b/images/nginx/README.md new file mode 100644 index 0000000..f365d02 --- /dev/null +++ b/images/nginx/README.md @@ -0,0 +1,13 @@ +dockerfiles-alt-nginx +====================== + +ALT dockerfile for nginx. + +Copy Dockerfile somewhere and build the image: +`$ docker build --rm -t /nginx .` + +And launch the nginx container: +`docker run -it -p 80:80 /nginx` + +It could be test via: +`curl localhost:80` diff --git a/images/python/Dockerfile.template b/images/python/Dockerfile.template new file mode 100644 index 0000000..3e67385 --- /dev/null +++ b/images/python/Dockerfile.template @@ -0,0 +1,15 @@ +FROM {{ registry }}{{ organization }}/base:{{ branch }} + +MAINTAINER alt-cloud + +RUN apt-get update && \ + apt-get install -y python3-module-pip \ + python3-module-setuptools \ + python3-dev \ + gcc \ + ; \ + rm -f /var/cache/apt/archives/*.rpm \ + /var/cache/apt/*.bin \ + /var/lib/apt/lists/*.* + +CMD ["python3"] diff --git a/images/python/README.md b/images/python/README.md new file mode 100644 index 0000000..3831f1f --- /dev/null +++ b/images/python/README.md @@ -0,0 +1,13 @@ +dockerfiles-alt-python +======================= + +ALT dockerfile for python. + +Image contains python(3) and tools to get upstream python modules. Main purpose +of the image is to run python apps using upstream modules. + +Copy Dockerfile somewhere and build the image: +`$ docker build --rm -t /python .` + +And launch the python container: +`docker run -it /python` diff --git a/images/ruby/Dockerfile.template b/images/ruby/Dockerfile.template new file mode 100644 index 0000000..d15b911 --- /dev/null +++ b/images/ruby/Dockerfile.template @@ -0,0 +1,11 @@ +FROM {{ registry }}{{ alt_image }}:{{ branch }} + +MAINTAINER alt-cloud + +RUN apt-get update && \ + apt-get install -y irb; \ + rm -f /var/cache/apt/archives/*.rpm \ + /var/cache/apt/*.bin \ + /var/lib/apt/lists/*.* + +CMD ["irb"] diff --git a/images/ruby/README.md b/images/ruby/README.md new file mode 100644 index 0000000..4098454 --- /dev/null +++ b/images/ruby/README.md @@ -0,0 +1,10 @@ +dockerfiles-alt-ruby +===================== + +ALT dockerfile for ruby. + +Copy Dockerfile somewhere and build the image: +`$ docker build --rm -t /ruby .` + +And launch the ruby container: +`docker run -it /ruby` diff --git a/images/systemd/Dockerfile.template b/images/systemd/Dockerfile.template new file mode 100644 index 0000000..806cd98 --- /dev/null +++ b/images/systemd/Dockerfile.template @@ -0,0 +1,24 @@ +FROM {{ registry }}{{ organization }}/base:{{ branch }} + +MAINTAINER alt-cloud + +RUN apt-get update && \ + apt-get install -y systemd; \ + rm -f /var/cache/apt/archives/*.rpm \ + /var/cache/apt/*.bin \ + /var/lib/apt/lists/*.* + +RUN ( \ + cd /lib/systemd/system/sysinit.target.wants/; \ + for i in *; do \ + [ $i == systemd-tmpfiles-setup.service ] || rm -f $i; \ + done \ + ); \ + rm -f /lib/systemd/system/multi-user.target.wants/*;\ + rm -f /etc/systemd/system/*.wants/*;\ + rm -f /lib/systemd/system/local-fs.target.wants/*; \ + rm -f /lib/systemd/system/sockets.target.wants/*udev*; \ + rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \ + rm -f /lib/systemd/system/basic.target.wants/*; + +CMD ["/sbin/init"] diff --git a/images/systemd/README.md b/images/systemd/README.md new file mode 100644 index 0000000..131117d --- /dev/null +++ b/images/systemd/README.md @@ -0,0 +1,10 @@ +dockerfiles-alt-systemd +======================== + +ALT dockerfile for systemd. + +Copy Dockerfile somewhere and build the image: +`$ docker build --rm -t /systemd .` + +And launch the systemd container: +`docker run -it /systemd`