| Message ID | 20260609164032.1415124-2-sandeep.gundlupet-raju@amd.com |
|---|---|
| State | Accepted, archived |
| Commit | 67183015756fa364aadc32b6b0b4a52dcb33437f |
| Delegated to: | Tim Orling |
| Headers | show |
| Series | Add app dir support | expand |
merged. On Tue, Jun 9, 2026 at 9:40 AM Sandeep Gundlupet Raju < sandeep.gundlupet-raju@amd.com> wrote: > Add a new --app-dir command-line argument (default: /opt) to allow the > base directory used inside the containers to be configurable instead of > being hardcoded to /opt. > > Changes: > - dockersetup.py: add --app-dir argument; write APP_DIR to .env file via > new write_env_file() so docker-compose passes it as a build arg; update > edit_dockercompose() to expand build: block and inject APP_DIR build arg > reference, and rewrite volume mounts and celery --workdir accordingly; > propagate app_dir through setup_https(), check_connectivity(), and all > direct docker-compose run call sites > - Dockerfile: add ARG APP_DIR=/opt + ENV APP_DIR=${APP_DIR}; replace all > hardcoded /opt paths with ${APP_DIR} in COPY, RUN and CMD instructions > - docker/migrate.sh: replace /opt with ${APP_DIR:-/opt} > - docker/refreshlayers.sh: replace /opt with ${APP_DIR:-/opt} > - docker/updatelayers.sh: replace /opt with ${APP_DIR:-/opt} > - Pass app_dir to edit_settings_py() and replace the hardcoded > LAYER_FETCH_DIR = "/opt/workdir" with app_dir + "/workdir", so > the fetch directory respects the --app-dir option. > > AI-Generated: GitHub Copilot (Claude Sonnet 4.6) > > Signed-off-by: Sandeep Gundlupet Raju <sandeep.gundlupet-raju@amd.com> > --- > Dockerfile | 24 ++++++------ > docker/migrate.sh | 2 +- > docker/refreshlayers.sh | 2 +- > docker/updatelayers.sh | 2 +- > dockersetup.py | 86 +++++++++++++++++++++++++++++++++-------- > 5 files changed, 85 insertions(+), 31 deletions(-) > > diff --git a/Dockerfile b/Dockerfile > index 72f57d2..8e6e508 100644 > --- a/Dockerfile > +++ b/Dockerfile > @@ -3,6 +3,8 @@ > FROM ubuntu:jammy > LABEL maintainer="Michael Halstead <mhalstead@linuxfoundation.org>" > > +ARG APP_DIR=/opt > +ENV APP_DIR=${APP_DIR} > ENV PYTHONUNBUFFERED=1 \ > LANGUAGE=en_US \ > LANG=en_US.UTF-8 \ > @@ -55,22 +57,22 @@ RUN DEBIAN_FRONTEND=noninteractive apt-get update \ > && rm -rf /var/lib/apt/lists/* \ > && apt-get clean > > -COPY . /opt/layerindex > -RUN rm -rf /opt/layerindex/docker > -COPY docker/settings.py /opt/layerindex/settings.py > -COPY docker/refreshlayers.sh /opt/refreshlayers.sh > -COPY docker/updatelayers.sh /opt/updatelayers.sh > -COPY docker/migrate.sh /opt/migrate.sh > -COPY docker/connectivity_check.sh /opt/connectivity_check.sh > +COPY . ${APP_DIR}/layerindex > +RUN rm -rf ${APP_DIR}/layerindex/docker > +COPY docker/settings.py ${APP_DIR}/layerindex/settings.py > +COPY docker/refreshlayers.sh ${APP_DIR}/refreshlayers.sh > +COPY docker/updatelayers.sh ${APP_DIR}/updatelayers.sh > +COPY docker/migrate.sh ${APP_DIR}/migrate.sh > +COPY docker/connectivity_check.sh ${APP_DIR}/connectivity_check.sh > > -RUN mkdir /opt/workdir \ > +RUN mkdir ${APP_DIR}/workdir \ > && adduser --system --uid=500 layers \ > - && chown -R layers /opt/workdir > + && chown -R layers ${APP_DIR}/workdir > USER layers > > # Always copy in .gitconfig and proxy helper script (they need editing to > be active) > COPY docker/.gitconfig /home/layers/.gitconfig > -COPY docker/git-proxy /opt/bin/git-proxy > +COPY docker/git-proxy ${APP_DIR}/bin/git-proxy > > # Start Gunicorn > -CMD ["/usr/local/bin/gunicorn", "wsgi:application", "--workers=4", > "--bind=:5000", "--timeout=60", "--log-level=debug", > "--chdir=/opt/layerindex"] > +CMD ["/bin/sh", "-c", "/usr/local/bin/gunicorn wsgi:application > --workers=4 --bind=:5000 --timeout=60 --log-level=debug > --chdir=${APP_DIR}/layerindex"] > diff --git a/docker/migrate.sh b/docker/migrate.sh > index ca15368..bb9f646 100755 > --- a/docker/migrate.sh > +++ b/docker/migrate.sh > @@ -1,2 +1,2 @@ > #!/bin/bash > -python3 /opt/layerindex/manage.py migrate "$@" > +python3 ${APP_DIR:-/opt}/layerindex/manage.py migrate "$@" > diff --git a/docker/refreshlayers.sh b/docker/refreshlayers.sh > index 0c550bd..5adaf86 100755 > --- a/docker/refreshlayers.sh > +++ b/docker/refreshlayers.sh > @@ -1,3 +1,3 @@ > #!/bin/bash > -update=/opt/layerindex/layerindex/update.py > +update=${APP_DIR:-/opt}/layerindex/layerindex/update.py > $update -q -r > diff --git a/docker/updatelayers.sh b/docker/updatelayers.sh > index 21640ba..6f0e8f0 100755 > --- a/docker/updatelayers.sh > +++ b/docker/updatelayers.sh > @@ -1,3 +1,3 @@ > #!/bin/bash > -update=/opt/layerindex/layerindex/update.py > +update=${APP_DIR:-/opt}/layerindex/layerindex/update.py > $update -q > diff --git a/dockersetup.py b/dockersetup.py > index bc7478c..3a74eb3 100755 > --- a/dockersetup.py > +++ b/dockersetup.py > @@ -70,6 +70,7 @@ def get_args(): > parser.add_argument('--no-migrate', action="store_true", > default=False, help='Skip running database migrations') > parser.add_argument('--no-admin-user', action="store_true", > default=False, help='Skip adding admin user') > parser.add_argument('--no-connectivity', action="store_true", > default=False, help='Skip checking external network connectivity') > + parser.add_argument('--app-dir', type=str, help='Base directory > inside the container for application files. Default is %(default)s', > required=False, default='/opt') > > args = parser.parse_args() > > @@ -253,14 +254,16 @@ def yaml_comment(line): > > > # Add hostname, secret key, db info, and email host in docker-compose.yml > -def edit_dockercompose(hostname, dbpassword, dbapassword, secretkey, > rmqpassword, portmapping, letsencrypt, email_host, email_port, email_user, > email_password, email_ssl, email_tls): > +def edit_dockercompose(hostname, dbpassword, dbapassword, secretkey, > rmqpassword, portmapping, letsencrypt, email_host, email_port, email_user, > email_password, email_ssl, email_tls, app_dir='/opt'): > + > + in_layersapp_build = False > > def adjust_cert_mount_line(ln): > linesplit = ln.split(':') > if letsencrypt: > linesplit[1] = '/etc/letsencrypt' > else: > - linesplit[1] = '/opt/cert' > + linesplit[1] = app_dir + '/cert' > # This allows us to handle if there is a ":ro" or similar on the > end > return ':'.join(linesplit) > > @@ -305,6 +308,33 @@ def edit_dockercompose(hostname, dbpassword, > dbapassword, secretkey, rmqpassword > newlines.append(ucline + '\n') > else: > newlines.append(yaml_comment(line) + '\n') > + elif re.match(r'^\s+build:\s+\.$', line): > + # Convert inline 'build: .' to block form so we can pass > APP_DIR as a build arg > + indent = line[:len(line) - len(line.lstrip())] > + newlines.append(indent + 'build:\n') > + newlines.append(indent + ' context: .\n') > + newlines.append(indent + ' args:\n') > + newlines.append(indent + ' - APP_DIR=${APP_DIR}\n') > + in_layersapp_build = True > + continue > + elif '- APP_DIR=' in line: > + # Keep APP_DIR referencing the .env file (do not embed value > here) > + format = line[:line.find('- APP_DIR=')].replace('#', '') > + newlines.append(format + '- APP_DIR=${APP_DIR}\n') > + continue > + elif re.match(r'^\s+context:\s+\.$', line) and in_layersapp_build: > + in_layersapp_build = False > + newlines.append(line + '\n') > + continue > + elif ':/opt/workdir' in line: > + newlines.append(line.replace(':/opt/workdir', ':' + app_dir + > '/workdir') + '\n') > + continue > + elif ':/opt/layerindex-task-logs' in line: > + newlines.append(line.replace(':/opt/layerindex-task-logs', > ':' + app_dir + '/layerindex-task-logs') + '\n') > + continue > + elif '--workdir=/opt/layerindex' in line: > + newlines.append(line.replace('--workdir=/opt/layerindex', > '--workdir=' + app_dir + '/layerindex') + '\n') > + continue > elif "layersweb:" in line: > in_layersweb = True > newlines.append(line + "\n") > @@ -426,7 +456,7 @@ def edit_nginx_ssl_conf(hostname, https_port, certdir, > certfile, keyfile): > writefile("docker/nginx-ssl-edited.conf", ''.join(newlines)) > > > -def edit_settings_py(emailaddr): > +def edit_settings_py(emailaddr, app_dir='/opt'): > filedata = readfile('docker/settings.py') > newlines = [] > lines = filedata.splitlines() > @@ -444,6 +474,9 @@ def edit_settings_py(emailaddr): > newlines.append(" ('Admin', '%s'),\n" % emailaddr) > newlines.append(")\n") > continue > + elif line.lstrip().startswith('LAYER_FETCH_DIR'): > + newlines.append("LAYER_FETCH_DIR = \"%s/workdir\"\n" % > app_dir) > + continue > newlines.append(line + "\n") > writefile("docker/settings.py", ''.join(newlines)) > > @@ -474,9 +507,9 @@ def edit_dockerfile_web(hostname, no_https): > writefile("Dockerfile.web", ''.join(newlines)) > > > -def setup_https(hostname, http_port, https_port, letsencrypt, > letsencrypt_production, cert, cert_key, emailaddr): > +def setup_https(hostname, http_port, https_port, letsencrypt, > letsencrypt_production, cert, cert_key, emailaddr, app_dir='/opt'): > local_cert_dir = os.path.abspath('docker/certs') > - container_cert_dir = '/opt/cert' > + container_cert_dir = app_dir + '/cert' > if letsencrypt: > # Create dummy cert > container_cert_dir = '/etc/letsencrypt' > @@ -578,8 +611,26 @@ def edit_options_file(project_name): > f.write('project_name=%s\n' % project_name) > > > -def check_connectivity(): > - return_code = subprocess.call(['docker-compose', 'run', '--rm', > 'layersapp', '/opt/connectivity_check.sh'], shell=False) > +def write_env_file(app_dir): > + """Write APP_DIR to .env so docker-compose passes it as a build > arg.""" > + env_vars = {} > + try: > + with open('.env', 'r') as f: > + for line in f: > + line = line.strip() > + if '=' in line and not line.startswith('#'): > + k, v = line.split('=', 1) > + env_vars[k.strip()] = v.strip() > + except FileNotFoundError: > + pass > + env_vars['APP_DIR'] = app_dir > + with open('.env', 'w') as f: > + for k, v in env_vars.items(): > + f.write('%s=%s\n' % (k, v)) > + > + > +def check_connectivity(app_dir='/opt'): > + return_code = subprocess.call(['docker-compose', 'run', '--rm', > 'layersapp', app_dir + '/connectivity_check.sh'], shell=False) > if return_code != 0: > print("Connectivity check failed - if you are behind a proxy, > please check that you have correctly specified the proxy settings on the > command line (see --help for details)") > sys.exit(1) > @@ -741,24 +792,25 @@ if args.uninstall: > if args.update: > args.no_https = read_dockerfile_web() > if not args.no_https: > - container_cert_dir = '/opt/cert' > + container_cert_dir = args.app_dir + '/cert' > args.hostname, https_port, certdir, certfile, keyfile = > read_nginx_ssl_conf(container_cert_dir) > edit_nginx_ssl_conf(args.hostname, https_port, certdir, certfile, > keyfile) > else: > # Always edit these in case we switch from proxy to no proxy > edit_gitproxy(socks_proxy_host, socks_proxy_port, args.no_proxy) > edit_dockerfile(args.http_proxy, args.https_proxy, args.no_proxy) > + write_env_file(args.app_dir) > > - edit_dockercompose(args.hostname, dbpassword, dbapassword, secretkey, > rmqpassword, args.portmapping, args.letsencrypt, email_host, email_port, > args.email_user, args.email_password, args.email_ssl, args.email_tls) > + edit_dockercompose(args.hostname, dbpassword, dbapassword, secretkey, > rmqpassword, args.portmapping, args.letsencrypt, email_host, email_port, > args.email_user, args.email_password, args.email_ssl, args.email_tls, > args.app_dir) > > edit_dockerfile_web(args.hostname, args.no_https) > > - edit_settings_py(emailaddr) > + edit_settings_py(emailaddr, args.app_dir) > > edit_options_file(args.project_name) > > if not args.no_https: > - setup_https(args.hostname, http_port, https_port, > args.letsencrypt, args.letsencrypt_production, args.cert, args.cert_key, > emailaddr) > + setup_https(args.hostname, http_port, https_port, > args.letsencrypt, args.letsencrypt_production, args.cert, args.cert_key, > emailaddr, args.app_dir) > > ## Start up containers > return_code = subprocess.call(['docker-compose', 'up', '-d', '--build'], > shell=False) > @@ -768,7 +820,7 @@ if return_code != 0: > > if not (args.update or args.no_connectivity): > ## Run connectivity check > - check_connectivity() > + check_connectivity(args.app_dir) > > # Get real project name (if only there were a reasonable way to do > this... ugh) > real_project_name = '' > @@ -830,7 +882,7 @@ if not args.no_migrate: > env = os.environ.copy() > env['DATABASE_USER'] = 'root' > env['DATABASE_PASSWORD'] = dbapassword > - return_code = subprocess.call(['docker-compose', 'run', '--rm', '-e', > 'DATABASE_USER', '-e', 'DATABASE_PASSWORD', 'layersapp', > '/opt/migrate.sh'], shell=False, env=env) > + return_code = subprocess.call(['docker-compose', 'run', '--rm', '-e', > 'DATABASE_USER', '-e', 'DATABASE_PASSWORD', 'layersapp', args.app_dir + > '/migrate.sh'], shell=False, env=env) > if return_code != 0: > print("Applying migrations failed") > sys.exit(1) > @@ -864,13 +916,13 @@ if not args.update: > break > for volume in volumes: > volname = '%s_%s' % (real_project_name, volume) > - return_code = subprocess.call(['docker', 'run', '--rm', '-v', > '%s:/opt/mount' % volname, 'debian:stretch', 'chown', '500', '/opt/mount'], > shell=False) > + return_code = subprocess.call(['docker', 'run', '--rm', '-v', > '%s:%s/mount' % (volname, args.app_dir), 'debian:stretch', 'chown', '500', > args.app_dir + '/mount'], shell=False) > if return_code != 0: > print("Setting volume permissions for volume %s failed" % > volume) > sys.exit(1) > > ## Generate static assets. Run this command again to regenerate at any > time (when static assets in the code are updated) > -return_code = subprocess.call("docker-compose run --rm -e > STATIC_ROOT=/usr/share/nginx/html -v %s_layersstatic:/usr/share/nginx/html > layersapp /opt/layerindex/manage.py collectstatic --noinput" % > quote(real_project_name), shell = True) > +return_code = subprocess.call("docker-compose run --rm -e > STATIC_ROOT=/usr/share/nginx/html -v %s_layersstatic:/usr/share/nginx/html > layersapp %s/layerindex/manage.py collectstatic --noinput" % > (quote(real_project_name), args.app_dir), shell = True) > if return_code != 0: > print("Collecting static files failed") > sys.exit(1) > @@ -891,12 +943,12 @@ else: > if not args.update: > if not args.databasefile: > ## Set site name > - return_code = subprocess.call(['docker-compose', 'run', '--rm', > 'layersapp', '/opt/layerindex/layerindex/tools/site_name.py', host, > 'OpenEmbedded Layer Index'], shell=False) > + return_code = subprocess.call(['docker-compose', 'run', '--rm', > 'layersapp', args.app_dir + '/layerindex/layerindex/tools/site_name.py', > host, 'OpenEmbedded Layer Index'], shell=False) > > if not args.no_admin_user: > ## For a fresh database, create an admin account > print("Creating database superuser. Input user name and password > when prompted.") > - return_code = subprocess.call(['docker-compose', 'run', '--rm', > 'layersapp', '/opt/layerindex/manage.py', 'createsuperuser', '--email', > emailaddr], shell=False) > + return_code = subprocess.call(['docker-compose', 'run', '--rm', > 'layersapp', args.app_dir + '/layerindex/manage.py', 'createsuperuser', > '--email', emailaddr], shell=False) > if return_code != 0: > print("Creating superuser failed") > sys.exit(1) > -- > 2.43.0 > >
diff --git a/Dockerfile b/Dockerfile index 72f57d2..8e6e508 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,6 +3,8 @@ FROM ubuntu:jammy LABEL maintainer="Michael Halstead <mhalstead@linuxfoundation.org>" +ARG APP_DIR=/opt +ENV APP_DIR=${APP_DIR} ENV PYTHONUNBUFFERED=1 \ LANGUAGE=en_US \ LANG=en_US.UTF-8 \ @@ -55,22 +57,22 @@ RUN DEBIAN_FRONTEND=noninteractive apt-get update \ && rm -rf /var/lib/apt/lists/* \ && apt-get clean -COPY . /opt/layerindex -RUN rm -rf /opt/layerindex/docker -COPY docker/settings.py /opt/layerindex/settings.py -COPY docker/refreshlayers.sh /opt/refreshlayers.sh -COPY docker/updatelayers.sh /opt/updatelayers.sh -COPY docker/migrate.sh /opt/migrate.sh -COPY docker/connectivity_check.sh /opt/connectivity_check.sh +COPY . ${APP_DIR}/layerindex +RUN rm -rf ${APP_DIR}/layerindex/docker +COPY docker/settings.py ${APP_DIR}/layerindex/settings.py +COPY docker/refreshlayers.sh ${APP_DIR}/refreshlayers.sh +COPY docker/updatelayers.sh ${APP_DIR}/updatelayers.sh +COPY docker/migrate.sh ${APP_DIR}/migrate.sh +COPY docker/connectivity_check.sh ${APP_DIR}/connectivity_check.sh -RUN mkdir /opt/workdir \ +RUN mkdir ${APP_DIR}/workdir \ && adduser --system --uid=500 layers \ - && chown -R layers /opt/workdir + && chown -R layers ${APP_DIR}/workdir USER layers # Always copy in .gitconfig and proxy helper script (they need editing to be active) COPY docker/.gitconfig /home/layers/.gitconfig -COPY docker/git-proxy /opt/bin/git-proxy +COPY docker/git-proxy ${APP_DIR}/bin/git-proxy # Start Gunicorn -CMD ["/usr/local/bin/gunicorn", "wsgi:application", "--workers=4", "--bind=:5000", "--timeout=60", "--log-level=debug", "--chdir=/opt/layerindex"] +CMD ["/bin/sh", "-c", "/usr/local/bin/gunicorn wsgi:application --workers=4 --bind=:5000 --timeout=60 --log-level=debug --chdir=${APP_DIR}/layerindex"] diff --git a/docker/migrate.sh b/docker/migrate.sh index ca15368..bb9f646 100755 --- a/docker/migrate.sh +++ b/docker/migrate.sh @@ -1,2 +1,2 @@ #!/bin/bash -python3 /opt/layerindex/manage.py migrate "$@" +python3 ${APP_DIR:-/opt}/layerindex/manage.py migrate "$@" diff --git a/docker/refreshlayers.sh b/docker/refreshlayers.sh index 0c550bd..5adaf86 100755 --- a/docker/refreshlayers.sh +++ b/docker/refreshlayers.sh @@ -1,3 +1,3 @@ #!/bin/bash -update=/opt/layerindex/layerindex/update.py +update=${APP_DIR:-/opt}/layerindex/layerindex/update.py $update -q -r diff --git a/docker/updatelayers.sh b/docker/updatelayers.sh index 21640ba..6f0e8f0 100755 --- a/docker/updatelayers.sh +++ b/docker/updatelayers.sh @@ -1,3 +1,3 @@ #!/bin/bash -update=/opt/layerindex/layerindex/update.py +update=${APP_DIR:-/opt}/layerindex/layerindex/update.py $update -q diff --git a/dockersetup.py b/dockersetup.py index bc7478c..3a74eb3 100755 --- a/dockersetup.py +++ b/dockersetup.py @@ -70,6 +70,7 @@ def get_args(): parser.add_argument('--no-migrate', action="store_true", default=False, help='Skip running database migrations') parser.add_argument('--no-admin-user', action="store_true", default=False, help='Skip adding admin user') parser.add_argument('--no-connectivity', action="store_true", default=False, help='Skip checking external network connectivity') + parser.add_argument('--app-dir', type=str, help='Base directory inside the container for application files. Default is %(default)s', required=False, default='/opt') args = parser.parse_args() @@ -253,14 +254,16 @@ def yaml_comment(line): # Add hostname, secret key, db info, and email host in docker-compose.yml -def edit_dockercompose(hostname, dbpassword, dbapassword, secretkey, rmqpassword, portmapping, letsencrypt, email_host, email_port, email_user, email_password, email_ssl, email_tls): +def edit_dockercompose(hostname, dbpassword, dbapassword, secretkey, rmqpassword, portmapping, letsencrypt, email_host, email_port, email_user, email_password, email_ssl, email_tls, app_dir='/opt'): + + in_layersapp_build = False def adjust_cert_mount_line(ln): linesplit = ln.split(':') if letsencrypt: linesplit[1] = '/etc/letsencrypt' else: - linesplit[1] = '/opt/cert' + linesplit[1] = app_dir + '/cert' # This allows us to handle if there is a ":ro" or similar on the end return ':'.join(linesplit) @@ -305,6 +308,33 @@ def edit_dockercompose(hostname, dbpassword, dbapassword, secretkey, rmqpassword newlines.append(ucline + '\n') else: newlines.append(yaml_comment(line) + '\n') + elif re.match(r'^\s+build:\s+\.$', line): + # Convert inline 'build: .' to block form so we can pass APP_DIR as a build arg + indent = line[:len(line) - len(line.lstrip())] + newlines.append(indent + 'build:\n') + newlines.append(indent + ' context: .\n') + newlines.append(indent + ' args:\n') + newlines.append(indent + ' - APP_DIR=${APP_DIR}\n') + in_layersapp_build = True + continue + elif '- APP_DIR=' in line: + # Keep APP_DIR referencing the .env file (do not embed value here) + format = line[:line.find('- APP_DIR=')].replace('#', '') + newlines.append(format + '- APP_DIR=${APP_DIR}\n') + continue + elif re.match(r'^\s+context:\s+\.$', line) and in_layersapp_build: + in_layersapp_build = False + newlines.append(line + '\n') + continue + elif ':/opt/workdir' in line: + newlines.append(line.replace(':/opt/workdir', ':' + app_dir + '/workdir') + '\n') + continue + elif ':/opt/layerindex-task-logs' in line: + newlines.append(line.replace(':/opt/layerindex-task-logs', ':' + app_dir + '/layerindex-task-logs') + '\n') + continue + elif '--workdir=/opt/layerindex' in line: + newlines.append(line.replace('--workdir=/opt/layerindex', '--workdir=' + app_dir + '/layerindex') + '\n') + continue elif "layersweb:" in line: in_layersweb = True newlines.append(line + "\n") @@ -426,7 +456,7 @@ def edit_nginx_ssl_conf(hostname, https_port, certdir, certfile, keyfile): writefile("docker/nginx-ssl-edited.conf", ''.join(newlines)) -def edit_settings_py(emailaddr): +def edit_settings_py(emailaddr, app_dir='/opt'): filedata = readfile('docker/settings.py') newlines = [] lines = filedata.splitlines() @@ -444,6 +474,9 @@ def edit_settings_py(emailaddr): newlines.append(" ('Admin', '%s'),\n" % emailaddr) newlines.append(")\n") continue + elif line.lstrip().startswith('LAYER_FETCH_DIR'): + newlines.append("LAYER_FETCH_DIR = \"%s/workdir\"\n" % app_dir) + continue newlines.append(line + "\n") writefile("docker/settings.py", ''.join(newlines)) @@ -474,9 +507,9 @@ def edit_dockerfile_web(hostname, no_https): writefile("Dockerfile.web", ''.join(newlines)) -def setup_https(hostname, http_port, https_port, letsencrypt, letsencrypt_production, cert, cert_key, emailaddr): +def setup_https(hostname, http_port, https_port, letsencrypt, letsencrypt_production, cert, cert_key, emailaddr, app_dir='/opt'): local_cert_dir = os.path.abspath('docker/certs') - container_cert_dir = '/opt/cert' + container_cert_dir = app_dir + '/cert' if letsencrypt: # Create dummy cert container_cert_dir = '/etc/letsencrypt' @@ -578,8 +611,26 @@ def edit_options_file(project_name): f.write('project_name=%s\n' % project_name) -def check_connectivity(): - return_code = subprocess.call(['docker-compose', 'run', '--rm', 'layersapp', '/opt/connectivity_check.sh'], shell=False) +def write_env_file(app_dir): + """Write APP_DIR to .env so docker-compose passes it as a build arg.""" + env_vars = {} + try: + with open('.env', 'r') as f: + for line in f: + line = line.strip() + if '=' in line and not line.startswith('#'): + k, v = line.split('=', 1) + env_vars[k.strip()] = v.strip() + except FileNotFoundError: + pass + env_vars['APP_DIR'] = app_dir + with open('.env', 'w') as f: + for k, v in env_vars.items(): + f.write('%s=%s\n' % (k, v)) + + +def check_connectivity(app_dir='/opt'): + return_code = subprocess.call(['docker-compose', 'run', '--rm', 'layersapp', app_dir + '/connectivity_check.sh'], shell=False) if return_code != 0: print("Connectivity check failed - if you are behind a proxy, please check that you have correctly specified the proxy settings on the command line (see --help for details)") sys.exit(1) @@ -741,24 +792,25 @@ if args.uninstall: if args.update: args.no_https = read_dockerfile_web() if not args.no_https: - container_cert_dir = '/opt/cert' + container_cert_dir = args.app_dir + '/cert' args.hostname, https_port, certdir, certfile, keyfile = read_nginx_ssl_conf(container_cert_dir) edit_nginx_ssl_conf(args.hostname, https_port, certdir, certfile, keyfile) else: # Always edit these in case we switch from proxy to no proxy edit_gitproxy(socks_proxy_host, socks_proxy_port, args.no_proxy) edit_dockerfile(args.http_proxy, args.https_proxy, args.no_proxy) + write_env_file(args.app_dir) - edit_dockercompose(args.hostname, dbpassword, dbapassword, secretkey, rmqpassword, args.portmapping, args.letsencrypt, email_host, email_port, args.email_user, args.email_password, args.email_ssl, args.email_tls) + edit_dockercompose(args.hostname, dbpassword, dbapassword, secretkey, rmqpassword, args.portmapping, args.letsencrypt, email_host, email_port, args.email_user, args.email_password, args.email_ssl, args.email_tls, args.app_dir) edit_dockerfile_web(args.hostname, args.no_https) - edit_settings_py(emailaddr) + edit_settings_py(emailaddr, args.app_dir) edit_options_file(args.project_name) if not args.no_https: - setup_https(args.hostname, http_port, https_port, args.letsencrypt, args.letsencrypt_production, args.cert, args.cert_key, emailaddr) + setup_https(args.hostname, http_port, https_port, args.letsencrypt, args.letsencrypt_production, args.cert, args.cert_key, emailaddr, args.app_dir) ## Start up containers return_code = subprocess.call(['docker-compose', 'up', '-d', '--build'], shell=False) @@ -768,7 +820,7 @@ if return_code != 0: if not (args.update or args.no_connectivity): ## Run connectivity check - check_connectivity() + check_connectivity(args.app_dir) # Get real project name (if only there were a reasonable way to do this... ugh) real_project_name = '' @@ -830,7 +882,7 @@ if not args.no_migrate: env = os.environ.copy() env['DATABASE_USER'] = 'root' env['DATABASE_PASSWORD'] = dbapassword - return_code = subprocess.call(['docker-compose', 'run', '--rm', '-e', 'DATABASE_USER', '-e', 'DATABASE_PASSWORD', 'layersapp', '/opt/migrate.sh'], shell=False, env=env) + return_code = subprocess.call(['docker-compose', 'run', '--rm', '-e', 'DATABASE_USER', '-e', 'DATABASE_PASSWORD', 'layersapp', args.app_dir + '/migrate.sh'], shell=False, env=env) if return_code != 0: print("Applying migrations failed") sys.exit(1) @@ -864,13 +916,13 @@ if not args.update: break for volume in volumes: volname = '%s_%s' % (real_project_name, volume) - return_code = subprocess.call(['docker', 'run', '--rm', '-v', '%s:/opt/mount' % volname, 'debian:stretch', 'chown', '500', '/opt/mount'], shell=False) + return_code = subprocess.call(['docker', 'run', '--rm', '-v', '%s:%s/mount' % (volname, args.app_dir), 'debian:stretch', 'chown', '500', args.app_dir + '/mount'], shell=False) if return_code != 0: print("Setting volume permissions for volume %s failed" % volume) sys.exit(1) ## Generate static assets. Run this command again to regenerate at any time (when static assets in the code are updated) -return_code = subprocess.call("docker-compose run --rm -e STATIC_ROOT=/usr/share/nginx/html -v %s_layersstatic:/usr/share/nginx/html layersapp /opt/layerindex/manage.py collectstatic --noinput" % quote(real_project_name), shell = True) +return_code = subprocess.call("docker-compose run --rm -e STATIC_ROOT=/usr/share/nginx/html -v %s_layersstatic:/usr/share/nginx/html layersapp %s/layerindex/manage.py collectstatic --noinput" % (quote(real_project_name), args.app_dir), shell = True) if return_code != 0: print("Collecting static files failed") sys.exit(1) @@ -891,12 +943,12 @@ else: if not args.update: if not args.databasefile: ## Set site name - return_code = subprocess.call(['docker-compose', 'run', '--rm', 'layersapp', '/opt/layerindex/layerindex/tools/site_name.py', host, 'OpenEmbedded Layer Index'], shell=False) + return_code = subprocess.call(['docker-compose', 'run', '--rm', 'layersapp', args.app_dir + '/layerindex/layerindex/tools/site_name.py', host, 'OpenEmbedded Layer Index'], shell=False) if not args.no_admin_user: ## For a fresh database, create an admin account print("Creating database superuser. Input user name and password when prompted.") - return_code = subprocess.call(['docker-compose', 'run', '--rm', 'layersapp', '/opt/layerindex/manage.py', 'createsuperuser', '--email', emailaddr], shell=False) + return_code = subprocess.call(['docker-compose', 'run', '--rm', 'layersapp', args.app_dir + '/layerindex/manage.py', 'createsuperuser', '--email', emailaddr], shell=False) if return_code != 0: print("Creating superuser failed") sys.exit(1)
Add a new --app-dir command-line argument (default: /opt) to allow the base directory used inside the containers to be configurable instead of being hardcoded to /opt. Changes: - dockersetup.py: add --app-dir argument; write APP_DIR to .env file via new write_env_file() so docker-compose passes it as a build arg; update edit_dockercompose() to expand build: block and inject APP_DIR build arg reference, and rewrite volume mounts and celery --workdir accordingly; propagate app_dir through setup_https(), check_connectivity(), and all direct docker-compose run call sites - Dockerfile: add ARG APP_DIR=/opt + ENV APP_DIR=${APP_DIR}; replace all hardcoded /opt paths with ${APP_DIR} in COPY, RUN and CMD instructions - docker/migrate.sh: replace /opt with ${APP_DIR:-/opt} - docker/refreshlayers.sh: replace /opt with ${APP_DIR:-/opt} - docker/updatelayers.sh: replace /opt with ${APP_DIR:-/opt} - Pass app_dir to edit_settings_py() and replace the hardcoded LAYER_FETCH_DIR = "/opt/workdir" with app_dir + "/workdir", so the fetch directory respects the --app-dir option. AI-Generated: GitHub Copilot (Claude Sonnet 4.6) Signed-off-by: Sandeep Gundlupet Raju <sandeep.gundlupet-raju@amd.com> --- Dockerfile | 24 ++++++------ docker/migrate.sh | 2 +- docker/refreshlayers.sh | 2 +- docker/updatelayers.sh | 2 +- dockersetup.py | 86 +++++++++++++++++++++++++++++++++-------- 5 files changed, 85 insertions(+), 31 deletions(-)