diff --git a/Dockerfile b/Dockerfile new file mode 100644 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,36 @@ +FROM fedora:28 +MAINTAINER Sébastien Santoro aka Dereckson + +RUN dnf -y install mod_perl git sudo perl-App-cpanminus perl-CPAN \ + gcc gcc-c++ make vim-enhanced perl-Software-License gd-devel \ + openssl-devel ImageMagick-devel graphviz patch patchutils \ + perl-GD perl-GDGraph perl-GDTextUtil && \ + dnf -y install https://dev.mysql.com/get/mysql-community-client-8.0.12-1.fc28.x86_64.rpm \ + https://dev.mysql.com/get/mysql-community-libs-8.0.12-1.fc28.x86_64.rpm \ + https://dev.mysql.com/get/mysql-community-devel-8.0.12-1.fc28.x86_64.rpm \ + https://dev.mysql.com/get/mysql-community-common-8.0.12-1.fc28.x86_64.rpm && \ + dnf -y update && \ + dnf clean all + +RUN useradd -m -G wheel -u 1000 -s /bin/bash bugzilla && \ + cpanm --quiet --notest --skip-installed DateTime && \ + cpanm --quiet --notest --skip-installed Module::Build && \ + cpanm --quiet --notest --skip-installed Software::License && \ + cpanm --quiet --notest --skip-installed Pod::Coverage && \ + cpanm --quiet --notest --skip-installed Cache::Memcached::GetParserXS && \ + cpanm --quiet --notest --skip-installed XMLRPC::Lite && \ + cpanm --quiet --notest --skip-installed DBD::mysql && \ + cpanm --quiet --notest --skip-installed Memoize && \ + cpanm --quiet --notest --skip-installed HTML::FormatText::WithLinks && \ + cpanm --quiet --notest --skip-installed Chart::Lines && \ + cpanm --quiet --notest --skip-installed Template::Plugin::GD::Image && \ + git clone -b 5.0 https://github.com/bugzilla/bugzilla.git /opt/bugzilla && \ + cd /opt/bugzilla && cpanm --quiet --notest --skip-installed --installdeps --with-recommends . && \ + chown -R bugzilla:bugzilla /opt/bugzilla && \ + rm /etc/httpd/conf.d/welcome.conf + +COPY files / + +EXPOSE 80 + +CMD ["/usr/local/sbin/init-container"] diff --git a/README.md b/README.md new file mode 100644 --- /dev/null +++ b/README.md @@ -0,0 +1,21 @@ +## Bugzilla Docker image + +Provide a Bugzilla stable version, with CPAN modules. + +### Usage + +To start a container linked against a MySQL container: + +```bash +$ docker run -dt -p 8080:80 --link mysql:somemysqlcontainer \ + -e DB_HOST=mysql -e DB_USER=bugs -e DB_PASSWORD=bugs \ + -e BUGZILLA_URL=https://bugzilla.domain.tld + nasqueron/bugzilla +``` + +To use networks, replace the `--link` option by a network configuration. + +### Credits + +The dependencies and the configuration variables to provide +are partially based on Dave Lawrence (dklawren) work. diff --git a/files/etc/httpd/conf.d/bugzilla.conf b/files/etc/httpd/conf.d/bugzilla.conf new file mode 100644 --- /dev/null +++ b/files/etc/httpd/conf.d/bugzilla.conf @@ -0,0 +1,26 @@ +# ------------------------------------------------------------- +# Bugzilla - General Apache configuration +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +User bugzilla +Group bugzilla + +ServerName localhost:80 + +PerlSwitches -w -T +PerlConfigRequire /opt/bugzilla/mod_perl.pl + + + ServerName localhost + DocumentRoot "/opt/bugzilla" + + AddHandler cgi-script .cgi + + + DirectoryIndex index.cgi + + Options Indexes FollowSymLinks MultiViews ExecCGI + AllowOverride All + Require all granted + + diff --git a/files/etc/httpd/conf.modules.d/00-mpm.conf b/files/etc/httpd/conf.modules.d/00-mpm.conf new file mode 100644 --- /dev/null +++ b/files/etc/httpd/conf.modules.d/00-mpm.conf @@ -0,0 +1,6 @@ +# ------------------------------------------------------------- +# Bugzilla - Apache MPM configuration +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +# Apache2::SizeLimit requires a non-threaded MPM. +LoadModule mpm_prefork_module modules/mod_mpm_prefork.so diff --git a/files/usr/local/bin/setup-bugzilla b/files/usr/local/bin/setup-bugzilla new file mode 100755 --- /dev/null +++ b/files/usr/local/bin/setup-bugzilla @@ -0,0 +1,184 @@ +#!/usr/bin/env perl + +# ------------------------------------------------------------- +# Bugzilla - provide configuration from environment +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +# Project: Nasqueron +# Created: 2018-10-05 +# License: Trivial work, not eligible to copyright +# Description: To wrap Bugzilla into a 12-factor app or to +# package it as a Docker container, extract the +# configuration from the environment to provide +# to the checksetup.pl script. +# ------------------------------------------------------------- + +use Cwd 'abs_path'; +use feature 'say'; +use File::Basename; +use File::Path qw(make_path); +use POSIX qw/strftime/; +use strict; +use warnings; + +# ------------------------------------------------------------- +# Check environment +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +my @mandatory_variables = ("DB_HOST", "DB_USER", "DB_PASSWORD", "DB_DATABASE", "BUGZILLA_URL"); + +my $isEnviromentValid = 1; +foreach my $key (@mandatory_variables) { + if (!exists $ENV{$key}) { + say STDERR "Key missing: ", $key; + $isEnviromentValid = 0; + } +} + +if ($isEnviromentValid eq 0) { + exit 1; +} + +# ------------------------------------------------------------- +# Helper methods +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +sub generate_random_password { + my @alphanumeric = ('a'..'z', 'A'..'Z', 0..9); + return join '', map $alphanumeric[rand @alphanumeric], 0..16; +} + +sub run { + my $dir = shift; + my $command = shift; + + chdir($dir); + system($command); + return $? >> 8; +} + +sub get_value { + my $value = shift; + + if ($value =~ /^\d+?$/) { + return $value; + } + + return '\'' . $value . '\''; +} + +sub create_directory_for_file { + my $filename = shift; + my $dir = dirname($filename); + + if (-e $dir) { + if (!-d $dir) { + die "Can't create directory: this is currently a file -- " . $dir; + } + + return; + } + + say STDERR "Creating directory " . $dir; + make_path($dir); +} + +sub save_configuration_hints { + my $filename = shift; + my $answers = shift; + + create_directory_for_file($filename); + open(my $fd, '>', $filename) or die "Can't open the configuration hints file " . $filename; + + say $fd "# Configurations hints for Bugzilla setup"; + say $fd "# Autogenerated by ", abs_path($0); + say $fd "# at ", strftime("%Y-%m-%d %H:%M:%S", localtime); + say $fd ""; + + foreach my $key (keys %{ $answers }) { + say $fd '$answer{\'', $key, '\'} = ', get_value($answers->{$key}), ';'; + } +} + +# ------------------------------------------------------------- +# Provide admin credentials if needed +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +my $admin_credentials_provided = 1; +my $username = ""; +my $password = ""; + +if (exists $ENV{"ADMIN_EMAIL"} ) { + $username = $ENV{"ADMIN_EMAIL"}; +} else { + $username = 'admin@domain.tld'; + $admin_credentials_provided = 0; +} + +if (exists $ENV{"ADMIN_PASSWORD"} ) { + $password = $ENV{"ADMIN_PASSWORD"}; +} else { + $password = generate_random_password(); + $admin_credentials_provided = 0; +} + +# ------------------------------------------------------------- +# Prepare configuration hints +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +my %answer = (); + +$answer{'db_driver'} = 'mysql'; +$answer{'db_host'} = $ENV{"DB_HOST"}; +$answer{'db_port'} = 3306; +$answer{'db_user'} = $ENV{"DB_USER"}; +$answer{'db_pass'} = $ENV{"DB_PASSWORD"}; +$answer{'db_name'} = $ENV{"DB_DATABASE"}; +$answer{'db_sock'} = ''; +$answer{'db_check'} = 1; + +$answer{'db_mysql_ssl_ca_file'} = ''; +$answer{'db_mysql_ssl_ca_path'} = ''; +$answer{'db_mysql_ssl_client_cert'} = ''; +$answer{'db_mysql_ssl_client_key'} = ''; + +$answer{'urlbase'} = $ENV{"BUGZILLA_URL"}; +$answer{'create_htaccess'} = 1; +$answer{'webservergroup'} = 'bugzilla'; +$answer{'use_suexec'} = 0; +$answer{'index_html'} = 0; + +$answer{'cvsbin'} = '/usr/bin/cvs'; +$answer{'interdiffbin'} = '/usr/bin/interdiff'; +$answer{'diffpath'} = '/usr/bin'; + + +$answer{'ADMIN_OK'} = 'Y'; +$answer{'ADMIN_EMAIL'} = $username; +$answer{'ADMIN_PASSWORD'} = $password; +$answer{'ADMIN_REALNAME'} = $ENV{"ADMIN_REALNAME"} || 'Admin'; + +$answer{'NO_PAUSE'} = 1; + +save_configuration_hints('/usr/local/lib/bugzilla/provide_configuration.pl', \%answer); + +# ------------------------------------------------------------- +# Report extra information when needed +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +if (!$admin_credentials_provided) { + say STDERR ""; + say STDERR "\e[31mAdministrator account has not been provided in the configuration."; + say STDERR "If no admin account is already defined in your database, this one will be created:"; + say STDERR ""; + say STDERR "\tE-mail ..... ", $username; + say STDERR "\tPassword ... ", $password; + say STDERR "\e[0m"; +} + +# ------------------------------------------------------------- +# Run setup +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +my $exit_code = run("/opt/bugzilla", "perl checksetup.pl /usr/local/lib/bugzilla/provide_configuration.pl"); + +exit $exit_code; diff --git a/files/usr/local/sbin/init-container b/files/usr/local/sbin/init-container new file mode 100644 --- /dev/null +++ b/files/usr/local/sbin/init-container @@ -0,0 +1,17 @@ +#!/bin/sh + +if [ ! -f .initialized ]; then + # Container is initialized according the environment variables + # passed to the container to setup the application. + + /usr/local/bin/setup-bugzilla + + EXIT_CODE=$? + if [ $EXIT_CODE -eq 0 ]; then + touch .initialized + else + exit $EXIT_CODE + fi +fi + +/usr/sbin/httpd -DFOREGROUND