From 1832ad5acb86d9bac68875e57495918194cd764b Mon Sep 17 00:00:00 2001 From: Shuai Lin Date: Tue, 15 Nov 2016 16:59:02 +0800 Subject: [PATCH] Re-organize the build/start phases. - ./launcher bootstrap => init seafile server data & letsencrypt, then build a local image based on seafileorg/server: - ./launcher start => start a container using the local image --- .dockerignore | 2 + image/base/my_init.d/99_mysql_setup.sh | 6 ++- image/seafile/Dockerfile | 3 -- launcher | 52 +++++++++++++++---- scripts/bootstrap.py | 38 +++++++++++--- scripts/start.py | 13 +---- scripts/utils/__init__.py | 11 +++- templates/Dockerfile.template | 18 +++++++ .../seafile.nginx.conf.template | 2 + 9 files changed, 110 insertions(+), 35 deletions(-) create mode 100644 templates/Dockerfile.template rename image/seafile/seafile.nginx.conf => templates/seafile.nginx.conf.template (97%) diff --git a/.dockerignore b/.dockerignore index f54cb69..856300d 100644 --- a/.dockerignore +++ b/.dockerignore @@ -3,3 +3,5 @@ *.swp .DS_Store *.pyc + +shared/* diff --git a/image/base/my_init.d/99_mysql_setup.sh b/image/base/my_init.d/99_mysql_setup.sh index 83b10ee..aef7703 100755 --- a/image/base/my_init.d/99_mysql_setup.sh +++ b/image/base/my_init.d/99_mysql_setup.sh @@ -7,13 +7,15 @@ if [[ ! -d /var/lib/mysql/mysql ]]; then echo 'Rebuilding mysql data dir' chown -R mysql.mysql /var/lib/mysql - mysql_install_db > /dev/null + + mysql_install_db >/var/log/mysql-bootstrap.log 2>&1 + # TODO: print the log if mysql_install_db fails rm -rf /var/run/mysqld/* echo 'Starting mysqld' # The sleep 1 is there to make sure that inotifywait starts up before the socket is created - mysqld_safe & + mysqld_safe >>/var/log/bootstrap-mysql.log & echo 'Waiting for mysqld to come online' while [[ ! -x /var/run/mysqld/mysqld.sock ]]; do diff --git a/image/seafile/Dockerfile b/image/seafile/Dockerfile index 98ccd2e..b26f4dd 100644 --- a/image/seafile/Dockerfile +++ b/image/seafile/Dockerfile @@ -9,6 +9,3 @@ RUN mkdir -p /opt/seafile/ && \ RUN mkdir -p /etc/my_init.d ADD create_data_links.sh /etc/my_init.d/create_data_links.sh - -RUN mkdir -p /templates/ -ADD seafile.nginx.conf /templates/seafile.nginx.conf diff --git a/launcher b/launcher index db453b7..bcf6a81 100755 --- a/launcher +++ b/launcher @@ -5,6 +5,7 @@ set -o pipefail version=6.0.5 image=seafileorg/server:$version +local_image=local_seafile/server:latest dockerdir=$(cd "$(dirname $0)"; pwd -P) sharedir=$dockerdir/shared installdir=/opt/seafile/seafile-server-$version @@ -40,6 +41,27 @@ set_ports() { ports="" } +set_bootstrap_volumes() { + local mounts + init_shared + + mounts=( + $sharedir:/shared + $sharedir/logs/var-log:/var/log + $sharedir/db:/var/lib/mysql + $dockerdir/bootstrap:/bootstrap + $dockerdir/scripts:/scripts:ro + $dockerdir/templates:/templates:ro + $dockerdir/scripts/tmp/check_init_admin.py:$installdir/check_init_admin.py:ro + $sharedir/.bash_history:/root/.bash_history + ) + volumes="" + local m + for m in ${mounts[*]}; do + volumes="$volumes -v $m" + done +} + set_volumes() { local mounts init_shared @@ -48,9 +70,6 @@ set_volumes() { $sharedir:/shared $sharedir/logs/var-log:/var/log $sharedir/db:/var/lib/mysql - $dockerdir/bootstrap:/bootstrap:ro - $dockerdir/scripts:/scripts:ro - $dockerdir/scripts/tmp/check_init_admin.py:$installdir/check_init_admin.py:ro $sharedir/.bash_history:/root/.bash_history ) volumes="" @@ -65,17 +84,28 @@ bootstrap() { if [[ ! -e $bootstrap_conf ]]; then err_and_quit "The file $bootstrap_conf doesn't exist. Have you run seafile-server-setup?" fi + + # First initialize seafile server and letsencrypt + set_bootstrap_volumes + set_ports + + docker run --rm -it --name seafile-bootstrap -e SEAFILE_BOOTSRAP=1 $volumes $ports $image /sbin/my_init -- /scripts/bootstrap.py + + docker build -f bootstrap/generated/Dockerfile -t local_seafile/server:latest . +} + +oldstart() { set_volumes set_ports - docker run --rm -it --name seafile-bootstrap -e SEAFILE_BOOTSRAP=1 $volumes $ports $image /sbin/my_init -- /scripts/bootstrap.py + docker run --rm -it --name seafile $volumes $ports $image \ + /sbin/my_init -- bash -l + # /sbin/my_init -- /scripts/start.py } start() { set_volumes set_ports - docker run --rm -it --name seafile $volumes $ports $image \ - /sbin/my_init -- /scripts/start.py - # /sbin/my_init -- bash -l + docker run --rm -it --name seafile $volumes $ports $local_image } enter() { @@ -87,10 +117,10 @@ main() { while [[ $# -gt 0 ]] do case "$1" in - bootstrap|start|enter) action=$1 ; shift 1 ;; - --debug) debug=true ; shift 1 ;; - --dummy) dummy=$2 ; shift 2 ;; - *) err_and_quit "Argument error. Please see help." ;; + bootstrap|oldstart|start|enter) action=$1 ; shift 1 ;; + --debug) debug=true ; shift 1 ;; + --dummy) dummy=$2 ; shift 2 ;; + *) err_and_quit "Argument error. Please see help." ;; esac done "$action" diff --git a/scripts/bootstrap.py b/scripts/bootstrap.py index e129191..d7fe3ac 100755 --- a/scripts/bootstrap.py +++ b/scripts/bootstrap.py @@ -13,14 +13,16 @@ import shutil import sys import uuid -from utils import call, get_conf, get_install_dir, get_script, render_nginx_conf +from utils import call, get_conf, get_install_dir, get_script, render_template, get_seafile_version +seafile_version = get_seafile_version() installdir = get_install_dir() topdir = dirname(installdir) shared_seafiledir = '/shared/seafile' ssl_dir = '/shared/ssl' +generated_dir = '/bootstrap/generated' -def init_letsencryt(): +def init_letsencrypt(): if not exists(ssl_dir): os.mkdir(ssl_dir) @@ -29,17 +31,41 @@ def init_letsencryt(): 'https': False, 'domain': domain, } - render_nginx_conf('/templates/seafile.nginx.conf', - '/etc/nginx/sites-enabled/seafile.nginx.conf', context) + + # Create a temporary nginx conf to start a server, which would accessed by letsencrypt + render_template('/templates/seafile.nginx.conf.template', + '/etc/nginx/sites-enabled/seafile.nginx.conf', context) call('nginx -s reload') call('/scripts/ssl.sh {0} {1}'.format(ssl_dir, domain)) + # Now create the final nginx configuratin + context = { + 'https': True, + 'domain': domain, + } + render_template('/templates/seafile.nginx.conf.template', join(generated_dir, 'seafile.nginx.conf'), context) + +def is_https(): + return get_conf('server.https', '').lower() == 'true' + +def generate_local_dockerfile(): + context = { + 'seafile_version': seafile_version, + 'https': is_https(), + 'domain': get_conf('server.domain'), + } + render_template('/templates/Dockerfile.template', join(generated_dir, 'Dockerfile'), context) + def main(): if not exists(shared_seafiledir): os.mkdir(shared_seafiledir) + if not exists(generated_dir): + os.mkdir(generated_dir) - if get_conf('server.https', '').lower() == 'true': - init_letsencryt() + generate_local_dockerfile() + + if is_https(): + init_letsencrypt() env = { 'SERVER_NAME': 'seafile', diff --git a/scripts/start.py b/scripts/start.py index 3410b9b..4693cdf 100755 --- a/scripts/start.py +++ b/scripts/start.py @@ -14,7 +14,7 @@ import shutil import sys import time -from utils import call, get_conf, get_install_dir, get_script, get_command_output, render_nginx_conf +from utils import call, get_conf, get_install_dir, get_script, get_command_output, render_template installdir = get_install_dir() topdir = dirname(installdir) @@ -30,18 +30,7 @@ def watch_controller(): print 'seafile controller exited unexpectedly.' sys.exit(1) -def init_https(): - domain = get_conf('server.hostname') - context = { - 'https': True, - 'domain': domain, - } - render_nginx_conf('/templates/seafile.nginx.conf', - '/etc/nginx/sites-enabled/seafile.nginx.conf', context) - call('nginx -t && nginx -s reload') - def main(): - init_https() admin_pw = { 'email': get_conf('admin.email'), 'password': get_conf('admin.password'), diff --git a/scripts/utils/__init__.py b/scripts/utils/__init__.py index 57089f2..0ea2208 100644 --- a/scripts/utils/__init__.py +++ b/scripts/utils/__init__.py @@ -4,6 +4,7 @@ from __future__ import print_function from ConfigParser import ConfigParser from contextlib import contextmanager import os +import datetime from os.path import abspath, basename, exists, dirname, join, isdir, expanduser import platform import sys @@ -221,9 +222,17 @@ def get_conf(key, default=None): return _config.get("server", key) if _config.has_option("server", key) \ else default -def render_nginx_conf(template, target, context): +def _add_default_context(context): + default_context = { + 'current_timestr': datetime.datetime.now().strftime('%m/%d/%Y %H:%M:%S'), + } + for k in default_context: + context.setdefault(k, default_context[k]) + +def render_template(template, target, context): from jinja2 import Environment, FileSystemLoader env = Environment(loader=FileSystemLoader(dirname(template))) + _add_default_context(context) content = env.get_template(basename(template)).render(**context) with open(target, 'w') as fp: fp.write(content) diff --git a/templates/Dockerfile.template b/templates/Dockerfile.template new file mode 100644 index 0000000..37b070a --- /dev/null +++ b/templates/Dockerfile.template @@ -0,0 +1,18 @@ +# -*- mode: dockerfile -*- +# This is a jinja2 template to generate the real Dockerfile to build the local image +FROM seafileorg/server:{{ seafile_version }} + +ADD scripts /scripts + +ADD bootstrap /bootstrap + +# This can be removed for seafile server 6.0.6 and later +ADD scripts/tmp/check_init_admin.py /opt/seafile/seafile-server-{{ seafile_version }}/check_init_admin.py + +ADD bootstrap/generated/seafile.nginx.conf /etc/nginx/sites-enabled/seafile.nginx.conf + +{% if https -%} +# TODO: add a cron job to renew letsencrypt +{% endif -%} + +CMD ["/sbin/my_init", "--", "/scripts/start.py"] diff --git a/image/seafile/seafile.nginx.conf b/templates/seafile.nginx.conf.template similarity index 97% rename from image/seafile/seafile.nginx.conf rename to templates/seafile.nginx.conf.template index ceac245..3585e20 100644 --- a/image/seafile/seafile.nginx.conf +++ b/templates/seafile.nginx.conf.template @@ -1,3 +1,5 @@ +# -*- mode: nginx -*- +# Auto generated at {{ current_timestr }} {% if https -%} server { listen 80;