├── .gitignore
├── ansible.cfg
├── .github
├── FUNDING.yml
└── workflows
│ └── build.yml
├── arm64
├── vhosts.conf
├── Dockerfile
└── docker-entrypoint.sh
├── arm32v7
├── vhosts.conf
└── Dockerfile
├── Dockerfile
├── docker-compose.yml
├── tests
├── download-method-git
│ └── docker-compose.yml
└── download-method-composer
│ └── docker-compose.yml
├── main.yml
├── docker-entrypoint.sh
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | web/*
2 |
--------------------------------------------------------------------------------
/ansible.cfg:
--------------------------------------------------------------------------------
1 | [defaults]
2 | nocows = true
3 | stdout_callback = yaml
4 | bin_ansible_callbacks = True
5 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: geerlingguy
4 | patreon: geerlingguy
5 |
--------------------------------------------------------------------------------
/arm64/vhosts.conf:
--------------------------------------------------------------------------------
1 | DirectoryIndex index.php index.html
2 |
3 |
4 | ServerName local.dev
5 | DocumentRoot "/var/www/html"
6 |
7 |
8 | AllowOverride All
9 | Options -Indexes +FollowSymLinks
10 | Require all granted
11 |
12 |
13 |
--------------------------------------------------------------------------------
/arm32v7/vhosts.conf:
--------------------------------------------------------------------------------
1 | DirectoryIndex index.php index.html
2 |
3 |
4 | ServerName local.dev
5 | DocumentRoot "/var/www/html"
6 |
7 |
8 | AllowOverride All
9 | Options -Indexes +FollowSymLinks
10 | Require all granted
11 |
12 |
13 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM geerlingguy/php-apache:8.2
2 |
3 | RUN apt-get update \
4 | && apt-get install -y mariadb-client git \
5 | && rm -rf /var/lib/apt/lists/*
6 |
7 | COPY docker-entrypoint.sh /usr/local/bin/
8 | RUN ln -s usr/local/bin/docker-entrypoint.sh / # For backwards compatibility.
9 | ENTRYPOINT ["docker-entrypoint.sh"]
10 |
11 | WORKDIR "/var/www/html"
12 |
13 | EXPOSE 80
14 | CMD ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]
15 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | ---
2 | version: '3'
3 |
4 | services:
5 | drupal:
6 | build: ./
7 | image: geerlingguy/drupal:latest
8 | container_name: drupal
9 | environment:
10 | DRUPAL_DATABASE_HOST: drupal-mysql
11 | DRUPAL_DATABASE_PORT: 3306
12 | DRUPAL_DATABASE_NAME: drupal
13 | DRUPAL_DATABASE_USERNAME: drupal
14 | DRUPAL_DATABASE_PASSWORD: drupal
15 | DRUPAL_DATABASE_PREFIX: drupal
16 | # Generate a salt with: `php -r "echo bin2hex(random_bytes(25));"`
17 | DRUPAL_HASH_SALT: db0de8a1556aa5348f87cfc950cd2c9641713d46e9412c8b05
18 | ports:
19 | - "80:80"
20 | restart: always
21 | # Uncomment the volumes line and set to the local path of your Drupal
22 | # installation, if you need to work with a local codebase.
23 | # volumes:
24 | # - ~/Sites/drupal-container:/var/www/html:rw,delegated
25 |
26 | mysql:
27 | image: mariadb:10
28 | container_name: drupal-mysql
29 | environment:
30 | MARIADB_RANDOM_ROOT_PASSWORD: 'yes'
31 | MARIADB_DATABASE: drupal
32 | MARIADB_USER: drupal
33 | MARIADB_PASSWORD: drupal
34 | ports:
35 | - "3306:3306"
36 |
--------------------------------------------------------------------------------
/tests/download-method-git/docker-compose.yml:
--------------------------------------------------------------------------------
1 | ---
2 | services:
3 | drupal:
4 | build: ./
5 | image: geerlingguy/drupal:latest
6 | container_name: drupal
7 | environment:
8 | DRUPAL_DATABASE_HOST: drupal-mysql
9 | DRUPAL_DATABASE_PORT: 3306
10 | DRUPAL_DATABASE_NAME: drupal
11 | DRUPAL_DATABASE_USERNAME: drupal
12 | DRUPAL_DATABASE_PASSWORD: drupal
13 | DRUPAL_DATABASE_PREFIX: drupal
14 | # Generate a salt with: `php -r "echo bin2hex(random_bytes(25));"`
15 | DRUPAL_HASH_SALT: db0de8a1556aa5348f87cfc950cd2c9641713d46e9412c8b05
16 | DRUPAL_DOWNLOAD_METHOD: git
17 | ports:
18 | - "80:80"
19 | restart: always
20 | # Uncomment the volumes line and set to the local path of your Drupal
21 | # installation, if you need to work with a local codebase.
22 | # volumes:
23 | # - ~/Sites/drupal-container:/var/www/html:rw,delegated
24 |
25 | mysql:
26 | image: mysql:5.7
27 | container_name: drupal-mysql
28 | environment:
29 | MYSQL_RANDOM_ROOT_PASSWORD: 'yes'
30 | MYSQL_DATABASE: drupal
31 | MYSQL_USER: drupal
32 | MYSQL_PASSWORD: drupal
33 | ports:
34 | - "3306:3306"
35 |
--------------------------------------------------------------------------------
/tests/download-method-composer/docker-compose.yml:
--------------------------------------------------------------------------------
1 | ---
2 | services:
3 | drupal:
4 | build: ./
5 | image: geerlingguy/drupal:latest
6 | container_name: drupal
7 | environment:
8 | DRUPAL_DATABASE_HOST: drupal-mysql
9 | DRUPAL_DATABASE_PORT: 3306
10 | DRUPAL_DATABASE_NAME: drupal
11 | DRUPAL_DATABASE_USERNAME: drupal
12 | DRUPAL_DATABASE_PASSWORD: drupal
13 | DRUPAL_DATABASE_PREFIX: drupal
14 | # Generate a salt with: `php -r "echo bin2hex(random_bytes(25));"`
15 | DRUPAL_HASH_SALT: db0de8a1556aa5348f87cfc950cd2c9641713d46e9412c8b05
16 | DRUPAL_DOWNLOAD_METHOD: composer
17 | DRUPAL_PROJECT_ROOT: /var/www/html
18 | APACHE_DOCUMENT_ROOT: /var/www/html/web
19 | ports:
20 | - "80:80"
21 | restart: always
22 | # Uncomment the volumes line and set to the local path of your Drupal
23 | # installation, if you need to work with a local codebase.
24 | # volumes:
25 | # - ~/Sites/drupal-container:/var/www/html:rw,delegated
26 |
27 | mysql:
28 | image: mysql:5.7
29 | container_name: drupal-mysql
30 | environment:
31 | MYSQL_RANDOM_ROOT_PASSWORD: 'yes'
32 | MYSQL_DATABASE: drupal
33 | MYSQL_USER: drupal
34 | MYSQL_PASSWORD: drupal
35 | ports:
36 | - "3306:3306"
37 |
--------------------------------------------------------------------------------
/arm32v7/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM balenalib/raspberrypi3-debian:bookworm
2 |
3 | # Add Ondrej Sury's apt repo and requirements.
4 | RUN sudo apt-get update \
5 | && sudo apt-get install apt-transport-https lsb-release ca-certificates wget git \
6 | && sudo wget -O /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg \
7 | && echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list \
8 | && rm -rf /var/lib/apt/lists/*
9 |
10 | # Install Apache, PHP
11 | RUN sudo apt-get update \
12 | && sudo apt-get install -y \
13 | apache2 libapache2-mod-php libpcre3-dev unzip \
14 | php8.2-common:armhf php8.2-dev:armhf php8.2-gd:armhf php8.2-curl:armhf php8.2-imap:armhf php8.2-opcache:armhf php8.2-xml:armhf php8.2-mbstring:armhf php8.2-mysql:armhf php8.2-zip:armhf php-apcu:armhf \
15 | mariadb-client \
16 | && rm -rf /var/lib/apt/lists/*
17 |
18 | COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
19 |
20 | RUN a2enmod rewrite
21 |
22 | RUN rm -f /etc/apache2/sites-enabled/000-default.conf
23 | COPY vhosts.conf /etc/apache2/sites-enabled/vhosts.conf
24 |
25 | COPY docker-entrypoint.sh /usr/local/bin/
26 | RUN ln -s usr/local/bin/docker-entrypoint.sh / # For backwards compatibility.
27 | ENTRYPOINT ["docker-entrypoint.sh"]
28 |
29 | WORKDIR "/var/www/html"
30 |
31 | EXPOSE 80
32 | CMD ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]
33 |
--------------------------------------------------------------------------------
/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - hosts: localhost
3 | connection: local
4 | gather_facts: no
5 |
6 | vars:
7 | build_amd64: true
8 | build_arm64: true
9 | build_arm32: true
10 |
11 | tasks:
12 | - name: Build the x86 Docker image from the main Dockerfile.
13 | docker_image:
14 | build:
15 | path: ./
16 | nocache: true
17 | pull: true
18 | name: geerlingguy/drupal
19 | tag: latest
20 | source: build
21 | force_source: true
22 | when: build_amd64 | bool
23 |
24 | - name: Copy entrypoint into arm64 folder temporarily.
25 | copy:
26 | src: docker-entrypoint.sh
27 | dest: arm64/docker-entrypoint.sh
28 | mode: 0755
29 |
30 | - name: Build the arm64 Docker image from the arm Dockerfile.
31 | docker_image:
32 | build:
33 | path: ./arm64/
34 | nocache: true
35 | pull: true
36 | platform: linux/arm64
37 | name: geerlingguy/drupal
38 | tag: latest-arm64
39 | source: build
40 | force_source: true
41 | when: build_arm64 | bool
42 |
43 | - name: Remove temporary entrypoint file.
44 | file:
45 | path: arm64/docker-entrypoint.sh
46 | state: absent
47 |
48 | - name: Copy entrypoint into arm32v7 folder temporarily.
49 | copy:
50 | src: docker-entrypoint.sh
51 | dest: arm32v7/docker-entrypoint.sh
52 | mode: 0755
53 |
54 | - name: Build the arm32v7 Docker image from the arm Dockerfile.
55 | docker_image:
56 | build:
57 | path: ./arm32v7/
58 | nocache: true
59 | pull: true
60 | name: geerlingguy/drupal
61 | tag: latest-arm32v7
62 | source: build
63 | force_source: true
64 | when: build_arm32 | bool
65 |
66 | - name: Remove temporary entrypoint file.
67 | file:
68 | path: arm32v7/docker-entrypoint.sh
69 | state: absent
70 |
--------------------------------------------------------------------------------
/arm64/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM debian:bookworm-slim
2 |
3 | RUN echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections
4 |
5 | ENV php_version="8.2"
6 |
7 | # Add Ondrej Sury's apt repo and requirements.
8 | RUN apt-get update \
9 | && apt-get install -y apt-transport-https lsb-release ca-certificates curl wget git \
10 | && wget -O /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg \
11 | && echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list \
12 | && rm -rf /var/lib/apt/lists/*
13 |
14 | # Install Apache and PHP.
15 | RUN apt-get update \
16 | && apt-get install -y \
17 | apache2 libapache2-mod-php${php_version} libpcre3-dev unzip \
18 | php${php_version}-common php${php_version}-dev php${php_version}-gd php${php_version}-curl php${php_version}-imap php${php_version}-opcache php${php_version}-xml php${php_version}-mbstring php${php_version}-mysql php${php_version}-zip php${php_version}-apcu \
19 | mariadb-client --no-install-recommends \
20 | && rm -rf /var/lib/apt/lists/*
21 |
22 | # Force specific version of PHP.
23 | RUN update-alternatives --set php /usr/bin/php${php_version} \
24 | && update-alternatives --set phar /usr/bin/phar${php_version} \
25 | && update-alternatives --set phar.phar /usr/bin/phar.phar${php_version} \
26 | && update-alternatives --set phpize /usr/bin/phpize${php_version} \
27 | && update-alternatives --set php-config /usr/bin/php-config${php_version}
28 |
29 | COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
30 |
31 | RUN a2enmod rewrite
32 |
33 | RUN rm -f /etc/apache2/sites-enabled/000-default.conf
34 | COPY vhosts.conf /etc/apache2/sites-enabled/vhosts.conf
35 |
36 | COPY docker-entrypoint.sh /usr/local/bin/
37 | RUN ln -s usr/local/bin/docker-entrypoint.sh / # For backwards compatibility.
38 | ENTRYPOINT ["docker-entrypoint.sh"]
39 |
40 | WORKDIR "/var/www/html"
41 |
42 | EXPOSE 80
43 | CMD ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]
44 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: Build
3 |
4 | on:
5 | pull_request:
6 | push:
7 | branches:
8 | - master
9 | schedule:
10 | - cron: "15 3 * * 0"
11 |
12 | env:
13 | ANSIBLE_FORCE_COLOR: true
14 |
15 | jobs:
16 | # Test the images build and work correctly.
17 | test:
18 | name: Test
19 | runs-on: ubuntu-latest
20 | strategy:
21 | matrix:
22 | compose_dir:
23 | - '.'
24 | # - 'tests/download-method-git' # Not working as of 2021-03-01.
25 | - 'tests/download-method-composer'
26 |
27 | steps:
28 | - uses: actions/checkout@v2
29 |
30 | - name: Set up Python 3.
31 | uses: actions/setup-python@v2
32 | with:
33 | python-version: '3.x'
34 |
35 | - name: Install prerequisites.
36 | run: pip3 install ansible docker six
37 |
38 | # See: https://github.com/geerlingguy/ansible-role-mysql/issues/422
39 | - name: Disable AppArmor.
40 | run: |
41 | set -x
42 | sudo apt-get install apparmor-profiles
43 | sudo ln -s /etc/apparmor.d/usr.sbin.mysqld /etc/apparmor.d/disable/
44 | sudo apparmor_parser -R /etc/apparmor.d/usr.sbin.mysqld
45 |
46 | - name: Build the amd64 image.
47 | run: >
48 | ansible-playbook main.yml --extra-vars "{build_arm32: false, build_arm64: false}"
49 |
50 | - name: Run the amd64 image and test it.
51 | run: |
52 | attempts=0
53 | max_attempts=60
54 |
55 | cd ${{ matrix.compose_dir }}
56 | docker compose up -d
57 |
58 | echo "Waiting for Drupal to complete setup."
59 | until $(curl --output /dev/null --silent --head --fail http://localhost/); do
60 | if [ ${attempts} -eq ${max_attempts} ];then
61 | echo "Timeout while waiting for Drupal to complete setup."
62 | exit 1
63 | fi
64 |
65 | printf '.'
66 | attempts=$(($attempts+1))
67 | sleep 5
68 | done
69 |
70 | # If on master branch, build and release images.
71 | release:
72 | name: Release
73 | runs-on: ubuntu-latest
74 | needs: test
75 | if: github.ref == 'refs/heads/master'
76 |
77 | steps:
78 | - uses: actions/checkout@v2
79 |
80 | - name: Set up Python 3.
81 | uses: actions/setup-python@v2
82 | with:
83 | python-version: '3.x'
84 |
85 | - name: Set up QEMU
86 | uses: docker/setup-qemu-action@v1
87 |
88 | - name: Set up Docker Buildx
89 | uses: docker/setup-buildx-action@v1
90 | with:
91 | install: true
92 |
93 | - name: Install prerequisites.
94 | run: pip3 install ansible docker six
95 |
96 | - name: Build the images.
97 | run: ansible-playbook main.yml
98 |
99 | - name: List all images for debugging.
100 | run: docker images
101 |
102 | - name: Login to DockerHub
103 | uses: docker/login-action@v1
104 | with:
105 | username: ${{ secrets.DOCKERHUB_USERNAME }}
106 | password: ${{ secrets.DOCKERHUB_TOKEN }}
107 |
108 | - name: Push images.
109 | run: |
110 | docker push geerlingguy/drupal:latest
111 | docker push geerlingguy/drupal:latest-arm64
112 | docker push geerlingguy/drupal:latest-arm32v7
113 |
--------------------------------------------------------------------------------
/docker-entrypoint.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #
3 | # Drupal container entrypoint.
4 | #
5 | # This entrypoint script will create a new Drupal codebase if one is not already
6 | # present in the APACHE_DOCUMENT_ROOT directory.
7 |
8 | set -e
9 |
10 | # Allow container to specify skipping cert validation.
11 | DRUPAL_DOWNLOAD_VERIFY_CERT=${DRUPAL_DOWNLOAD_VERIFY_CERT:-true}
12 |
13 | # Allow setting the way Drupal is downloaded (tarball, git, composer).
14 | DRUPAL_DOWNLOAD_METHOD=${DRUPAL_DOWNLOAD_METHOD:-tarball}
15 |
16 | # Drupal URLs and version options.
17 | DRUPAL_DOWNLOAD_URL="https://www.drupal.org/download-latest/tar.gz"
18 | DRUPAL_CLONE_URL=${DRUPAL_CLONE_URL:-"https://git.drupalcode.org/project/drupal.git"}
19 | DRUPAL_CLONE_BRANCH=${DRUPAL_CLONE_BRANCH:-"10.3.x"}
20 | DRUPAL_PROJECT_VERSION=${DRUPAL_PROJECT_VERSION:-"^10@dev"}
21 |
22 | # Allow container to skip the download by setting this to false.
23 | DRUPAL_DOWNLOAD_IF_NOT_PRESENT=${DRUPAL_DOWNLOAD_IF_NOT_PRESENT:-true}
24 |
25 | # Allow container to skip composer install step by setting this to false.
26 | DRUPAL_RUN_COMPOSER_INSTALL=${DRUPAL_RUN_COMPOSER_INSTALL:-true}
27 |
28 | # Project directories.
29 | APACHE_DOCUMENT_ROOT=${APACHE_DOCUMENT_ROOT:-"/var/www/html"}
30 | DRUPAL_PROJECT_ROOT=${DRUPAL_PROJECT_ROOT:-$APACHE_DOCUMENT_ROOT}
31 |
32 | # Allow users to override the docroot by setting an environment variable.
33 | if [ "$APACHE_DOCUMENT_ROOT" != "/var/www/html" ]; then
34 | sed -ri -e "s|\"/var/www/html\"|\"$APACHE_DOCUMENT_ROOT\"|g" /etc/apache2/sites-enabled/*.conf
35 | sed -ri -e "s|\"/var/www/html\"|\"$APACHE_DOCUMENT_ROOT\"|g" /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf
36 | fi
37 |
38 | # Download Drupal to $APACHE_DOCUMENT_ROOT if it's not present.
39 | if [ ! -f $APACHE_DOCUMENT_ROOT/index.php ] && [ $DRUPAL_DOWNLOAD_IF_NOT_PRESENT = true ]; then
40 | echo "Removing any existing files inside $APACHE_DOCUMENT_ROOT..."
41 | find $DRUPAL_PROJECT_ROOT -type f -maxdepth 1 -delete || true
42 |
43 | cd $DRUPAL_PROJECT_ROOT
44 | if [ "$DRUPAL_DOWNLOAD_METHOD" == 'tarball' ]; then
45 | echo "Downloading Drupal..."
46 | if [ $DRUPAL_DOWNLOAD_VERIFY_CERT = true ]; then
47 | curl -sSL $DRUPAL_DOWNLOAD_URL | tar -xz --strip-components=1
48 | else
49 | curl -sSLk $DRUPAL_DOWNLOAD_URL | tar -xz --strip-components=1
50 | fi
51 | mkdir -p /var/www/config/sync
52 | echo "Download complete!"
53 | elif [ "$DRUPAL_DOWNLOAD_METHOD" == 'git' ]; then
54 | echo "Cloning Drupal..."
55 | git clone --branch $DRUPAL_CLONE_BRANCH --single-branch $DRUPAL_CLONE_URL .
56 | echo "Clone complete!"
57 | elif [ "$DRUPAL_DOWNLOAD_METHOD" == 'composer' ]; then
58 | composer -n create-project drupal/recommended-project:$DRUPAL_PROJECT_VERSION .
59 | fi
60 |
61 | echo "Configuring settings.php with environment variables..."
62 | cp $APACHE_DOCUMENT_ROOT/sites/default/default.settings.php $APACHE_DOCUMENT_ROOT/sites/default/settings.php
63 | cat <> $APACHE_DOCUMENT_ROOT/sites/default/settings.php
64 | \$databases['default']['default'] = array (
65 | 'database' => '$DRUPAL_DATABASE_NAME',
66 | 'username' => '$DRUPAL_DATABASE_USERNAME',
67 | 'password' => '$DRUPAL_DATABASE_PASSWORD',
68 | 'prefix' => '$DRUPAL_DATABASE_PREFIX',
69 | 'host' => '$DRUPAL_DATABASE_HOST',
70 | 'port' => '$DRUPAL_DATABASE_PORT',
71 | 'namespace' => 'Drupal\\\\Core\\\\Database\\\\Driver\\\\mysql',
72 | 'driver' => 'mysql',
73 | );
74 | \$config_directories['sync'] = '../config/sync';
75 | \$settings['hash_salt'] = '$DRUPAL_HASH_SALT';
76 | EOF
77 |
78 | echo "Correcting permissions on /var/www..."
79 | chown -R www-data:www-data /var/www
80 |
81 | if [ $DRUPAL_RUN_COMPOSER_INSTALL = true ] && [ "$DRUPAL_DOWNLOAD_METHOD" != 'composer' ]; then
82 | echo "Running composer install..."
83 | composer install
84 | fi
85 |
86 | echo "Drupal codebase ready!"
87 | fi
88 |
89 | exec "$@"
90 |
--------------------------------------------------------------------------------
/arm64/docker-entrypoint.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #
3 | # Drupal container entrypoint.
4 | #
5 | # This entrypoint script will create a new Drupal codebase if one is not already
6 | # present in the APACHE_DOCUMENT_ROOT directory.
7 |
8 | set -e
9 |
10 | # Allow container to specify skipping cert validation.
11 | DRUPAL_DOWNLOAD_VERIFY_CERT=${DRUPAL_DOWNLOAD_VERIFY_CERT:-true}
12 |
13 | # Allow setting the way Drupal is downloaded (tarball, git, composer).
14 | DRUPAL_DOWNLOAD_METHOD=${DRUPAL_DOWNLOAD_METHOD:-tarball}
15 |
16 | # Drupal URLs and version options.
17 | DRUPAL_DOWNLOAD_URL="https://www.drupal.org/download-latest/tar.gz"
18 | DRUPAL_CLONE_URL=${DRUPAL_CLONE_URL:-"https://git.drupalcode.org/project/drupal.git"}
19 | DRUPAL_CLONE_BRANCH=${DRUPAL_CLONE_BRANCH:-"10.3.x"}
20 | DRUPAL_PROJECT_VERSION=${DRUPAL_PROJECT_VERSION:-"^10@dev"}
21 |
22 | # Allow container to skip the download by setting this to false.
23 | DRUPAL_DOWNLOAD_IF_NOT_PRESENT=${DRUPAL_DOWNLOAD_IF_NOT_PRESENT:-true}
24 |
25 | # Allow container to skip composer install step by setting this to false.
26 | DRUPAL_RUN_COMPOSER_INSTALL=${DRUPAL_RUN_COMPOSER_INSTALL:-true}
27 |
28 | # Project directories.
29 | APACHE_DOCUMENT_ROOT=${APACHE_DOCUMENT_ROOT:-"/var/www/html"}
30 | DRUPAL_PROJECT_ROOT=${DRUPAL_PROJECT_ROOT:-$APACHE_DOCUMENT_ROOT}
31 |
32 | # Allow users to override the docroot by setting an environment variable.
33 | if [ "$APACHE_DOCUMENT_ROOT" != "/var/www/html" ]; then
34 | sed -ri -e "s|\"/var/www/html\"|\"$APACHE_DOCUMENT_ROOT\"|g" /etc/apache2/sites-enabled/*.conf
35 | sed -ri -e "s|\"/var/www/html\"|\"$APACHE_DOCUMENT_ROOT\"|g" /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf
36 | fi
37 |
38 | # Download Drupal to $APACHE_DOCUMENT_ROOT if it's not present.
39 | if [ ! -f $APACHE_DOCUMENT_ROOT/index.php ] && [ $DRUPAL_DOWNLOAD_IF_NOT_PRESENT = true ]; then
40 | echo "Removing any existing files inside $APACHE_DOCUMENT_ROOT..."
41 | find $DRUPAL_PROJECT_ROOT -type f -maxdepth 1 -delete || true
42 |
43 | cd $DRUPAL_PROJECT_ROOT
44 | if [ "$DRUPAL_DOWNLOAD_METHOD" == 'tarball' ]; then
45 | echo "Downloading Drupal..."
46 | if [ $DRUPAL_DOWNLOAD_VERIFY_CERT = true ]; then
47 | curl -sSL $DRUPAL_DOWNLOAD_URL | tar -xz --strip-components=1
48 | else
49 | curl -sSLk $DRUPAL_DOWNLOAD_URL | tar -xz --strip-components=1
50 | fi
51 | mkdir -p /var/www/config/sync
52 | echo "Download complete!"
53 | elif [ "$DRUPAL_DOWNLOAD_METHOD" == 'git' ]; then
54 | echo "Cloning Drupal..."
55 | git clone --branch $DRUPAL_CLONE_BRANCH --single-branch $DRUPAL_CLONE_URL .
56 | echo "Clone complete!"
57 | elif [ "$DRUPAL_DOWNLOAD_METHOD" == 'composer' ]; then
58 | composer -n create-project drupal/recommended-project:$DRUPAL_PROJECT_VERSION .
59 | fi
60 |
61 | echo "Configuring settings.php with environment variables..."
62 | cp $APACHE_DOCUMENT_ROOT/sites/default/default.settings.php $APACHE_DOCUMENT_ROOT/sites/default/settings.php
63 | cat <> $APACHE_DOCUMENT_ROOT/sites/default/settings.php
64 | \$databases['default']['default'] = array (
65 | 'database' => '$DRUPAL_DATABASE_NAME',
66 | 'username' => '$DRUPAL_DATABASE_USERNAME',
67 | 'password' => '$DRUPAL_DATABASE_PASSWORD',
68 | 'prefix' => '$DRUPAL_DATABASE_PREFIX',
69 | 'host' => '$DRUPAL_DATABASE_HOST',
70 | 'port' => '$DRUPAL_DATABASE_PORT',
71 | 'namespace' => 'Drupal\\\\Core\\\\Database\\\\Driver\\\\mysql',
72 | 'driver' => 'mysql',
73 | );
74 | \$config_directories['sync'] = '../config/sync';
75 | \$settings['hash_salt'] = '$DRUPAL_HASH_SALT';
76 | EOF
77 |
78 | echo "Correcting permissions on /var/www..."
79 | chown -R www-data:www-data /var/www
80 |
81 | if [ $DRUPAL_RUN_COMPOSER_INSTALL = true ] && [ "$DRUPAL_DOWNLOAD_METHOD" != 'composer' ]; then
82 | echo "Running composer install..."
83 | composer install
84 | fi
85 |
86 | echo "Drupal codebase ready!"
87 | fi
88 |
89 | exec "$@"
90 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Drupal Container (Built with Ansible)
2 |
3 | [](https://github.com/geerlingguy/drupal-container/actions/workflows/build.yml) [](https://hub.docker.com/r/geerlingguy/drupal/)
4 |
5 | This project is composed of three main parts:
6 |
7 | - **Ansible project**: This project is maintained on GitHub: [geerlingguy/drupal-container](https://github.com/geerlingguy/drupal-container). Please file issues, support requests, etc. against this GitHub repository.
8 | - **Docker Hub Image**: If you just want to use [the `geerlingguy/drupal` Docker image](https://hub.docker.com/r/geerlingguy/drupal/) in your project, you can pull it from Docker Hub.
9 | - **Ansible Role**: If you need a flexible Ansible role that's compatible with both traditional servers and containerized builds, check out [`geerlingguy.docker`](https://galaxy.ansible.com/geerlingguy/docker/) on Ansible Galaxy. (This is the Ansible role that does the bulk of the work in managing the Docker container.)
10 |
11 | ## Versions
12 |
13 | Currently maintained versions include:
14 |
15 | - `latest`
16 | - `latest-arm64`
17 | - `latest-arm32v7`
18 |
19 | ## Standalone Usage
20 |
21 | The easiest way to use this Docker image is to place the `docker-compose.yml` file included with this project in your Drupal site's root directory, then customize it to your liking, and run:
22 |
23 | docker compose up -d
24 |
25 | You should be able to access the Drupal site at `http://localhost/`, and if you're installing the first time, the Drupal installer UI should appear. Follow the directions and you'll end up with a brand new Drupal site!
26 |
27 | ### Automatic Drupal codebase generation
28 |
29 | The image downloads Drupal into `/var/www/html` if you don't have a Drupal codebase mounted into that path by default.
30 |
31 | You can override this behavior (if, for example, you are sharing your codebase into `/var/www/html/web` or elsewhere) by setting the environment variable `DRUPAL_DOWNLOAD_IF_NOT_PRESENT=false`.
32 |
33 | There are three methods you can use to generate a Drupal codebase if you don't have one mounted into this container (or `COPY`ed into the container via `Dockerfile`):
34 |
35 | - `DRUPAL_DOWNLOAD_METHOD=tarball` (default): Downloads the latest tarball version of Drupal core.
36 | - `DRUPAL_DOWNLOAD_METHOD=git`: Clones Drupal from the git source, with options:
37 | - `DRUPAL_CLONE_URL`: The URL from which Drupal is cloned.
38 | - `DRUPAL_CLONE_BRANCH`: The branch that is checked out.
39 | - `DRUPAL_DOWNLOAD_METHOD=composer`: Creates a new Drupal project using `composer create-project`. If using this method, you should also override the following variables:
40 | - `DRUPAL_PROJECT_ROOT=/var/www/html`
41 | - `APACHE_DOCUMENT_ROOT=/var/www/html/web`
42 |
43 | ### Drupal codebase
44 |
45 | To get your Drupal codebase into the container, you can either `COPY` it in using a Dockerfile, or mount a volume (e.g. when using the image for development). The included `docker-compose.yml` file assumes you have a Drupal codebase at the path `./web`, but you can customize the volume mount to point to wherever your Drupal docroot exists.
46 |
47 | If you don't supply a Drupal codebase in the container in `/var/www/html`, this container's `docker-entrypoint.sh` script will download Drupal for you (using the `DRUPAL_DOWNLOAD_VERSION`). By default the image uses the latest development release of Drupal, but you can override it and install a specific version by setting `DRUPAL_DOWNLOAD_VERSION` to that version number (e.g. `10.3.1`).
48 |
49 | ### Settings in `settings.php`
50 |
51 | Since it's best practice to _not_ include secrets like database credentials in your codebase, this Docker container recommends putting connection details into runtime environment variables, which you can include in your Drupal site's `settings.php` file via `getenv()`.
52 |
53 | For example, to set up the database connection, pass settings like `DRUPAL_DATABASE_NAME`:
54 |
55 | $databases['default']['default'] = [
56 | 'driver' => 'mysql',
57 | 'database' => getenv('DRUPAL_DATABASE_NAME'),
58 | 'username' => getenv('DRUPAL_DATABASE_USERNAME'),
59 | 'password' => getenv('DRUPAL_DATABASE_PASSWORD'),
60 | 'prefix' => getenv('DRUPAL_DATABASE_PREFIX'),
61 | 'host' => getenv('DRUPAL_DATABASE_HOST'),
62 | 'port' => getenv('DRUPAL_DATABASE_PORT'),
63 | ];
64 |
65 | You may also want to set a `DRUPAL_HASH_SALT` environment variable to drive the `$settings['hash_salt']` setting.
66 |
67 | ### Custom Apache document root
68 |
69 | The default Apache document root is `/var/www/html`. If your codebase needs to use a different docroot (e.g. `/var/www/html/web` for Composer-built Drupal projects), you should set the environment variable `APACHE_DOCUMENT_ROOT` to the appropriate directory, and the container will change the docroot when it starts up.
70 |
71 | ## Management with Ansible
72 |
73 | ### Prerequisites
74 |
75 | Before using this project to build and maintain Drupal images for Docker, you need to have the following installed:
76 |
77 | - [Docker Community Edition](https://docs.docker.com/engine/installation/) (for Mac, Windows, or Linux)
78 | - [Ansible](http://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html)
79 |
80 | ### Build the image
81 |
82 | Make sure Docker is running, and run the playbook to build the container image:
83 |
84 | ansible-playbook main.yml
85 |
86 | # Or just build one platform version (e.g. x86):
87 | ansible-playbook main.yml --extra-vars "{build_amd64: true, build_arm64: false, build_arm32: false}"
88 |
89 | Once the image is built, you can run `docker images` to see the `drupal` image that was generated.
90 |
91 | > Note: If you get an error like `Failed to import docker-py`, run `pip install docker-py`.
92 |
93 | If you want to quickly run the image and test that the `docker-entrypoint.sh` script works to grab a copy of the Drupal codebase, run it with:
94 |
95 | docker run -d -p 80:80 -v $PWD/web:/var/www/html:rw geerlingguy/drupal
96 |
97 | Then visit [http://localhost/](http://localhost/), and (after Drupal is downloaded and expanded) you should see the Drupal installer! You can drop the volume mount (`-v`) for a much faster startup, but then the codebase is downloaded and stored inside the container, and will vanish when you stop it.
98 |
99 | ### Push the image to Docker Hub
100 |
101 | Currently, the process for updating this image on Docker Hub is manual. Eventually this will be automated via Travis CI.
102 |
103 | 1. Log into Docker Hub on the command line:
104 |
105 | docker login --username=geerlingguy
106 |
107 | 1. Push to Docker Hub:
108 |
109 | docker push geerlingguy/drupal:latest
110 | docker push geerlingguy/drupal:latest-arm64
111 | docker push geerlingguy/drupal:latest-arm32v7
112 |
113 | ## License
114 |
115 | MIT / BSD
116 |
117 | ## Author Information
118 |
119 | This container build was created in 2018 by [Jeff Geerling](https://www.jeffgeerling.com/), author of [Ansible for DevOps](https://www.ansiblefordevops.com/).
120 |
--------------------------------------------------------------------------------