From 6433a67d52e6387e612f2118b0330bc944c250ac Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Fri, 16 Aug 2019 18:38:26 +0200 Subject: [PATCH 1/8] Added all docker stuff to the project --- .dockerignore | 23 +++ .travis.yml | 6 - Dockerfile | 53 ++++++ README.md | 2 +- build.sh | 4 +- composer.json | 2 +- data/travis/trigger_docker_build.sh | 20 --- docker/README.md | 204 +++++++++++++++++++++++ docker/config/shlink_in_docker.local.php | 175 +++++++++++++++++++ docker/docker-entrypoint.sh | 17 ++ phpcs.xml | 1 + 11 files changed, 476 insertions(+), 31 deletions(-) create mode 100644 .dockerignore create mode 100644 Dockerfile delete mode 100644 data/travis/trigger_docker_build.sh create mode 100644 docker/README.md create mode 100644 docker/config/shlink_in_docker.local.php create mode 100644 docker/docker-entrypoint.sh diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..56849556 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,23 @@ +config/autoload/*local* +data/infra +data/cache/* +data/log/* +data/locks/* +data/proxies/* +data/migrations_template.txt +data/GeoLite2-City.* +data/database.sqlite +data/shlink-tests.db +**/.gitignore +CHANGELOG.md +composer.lock +vendor +docs +indocker +docker-* +php* +infection.json +phpstan.neon +**/test* +build* +.github diff --git a/.travis.yml b/.travis.yml index 335a9130..e63a202d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -54,9 +54,3 @@ deploy: on: tags: true php: 7.2 - - provider: script - script: bash data/travis/trigger_docker_build.sh - skip_cleanup: true - on: - tags: true - php: 7.2 diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..0c8be534 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,53 @@ +FROM php:7.3.8-cli-alpine3.10 +LABEL maintainer="Alejandro Celaya " + +ENV SWOOLE_VERSION 4.3.3 +ENV COMPOSER_VERSION 1.9.0 + +WORKDIR /etc/shlink + +RUN \ + # Install mysl and calendar + docker-php-ext-install -j"$(nproc)" pdo_mysql calendar && \ + # Install sqlite + apk add --no-cache sqlite-libs sqlite-dev && \ + docker-php-ext-install -j"$(nproc)" pdo_sqlite && \ + # Install postgres + apk add --no-cache postgresql-dev && \ + docker-php-ext-install -j"$(nproc)" pdo_pgsql && \ + # [Deprecated] Install intl + apk add --no-cache icu-dev && \ + docker-php-ext-install -j"$(nproc)" intl && \ + # Install zip and gd + apk add --no-cache libzip-dev zlib-dev libpng-dev && \ + docker-php-ext-install -j"$(nproc)" zip gd + +# Install swoole +# First line fixes an error when installing pecl extensions. Found in https://github.com/docker-library/php/issues/233 +RUN apk add --no-cache --virtual .phpize-deps $PHPIZE_DEPS && \ + pecl install swoole-${SWOOLE_VERSION} && \ + docker-php-ext-enable swoole && \ + apk del .phpize-deps + +# Install shlink +COPY . . +RUN rm -rf ./docker && \ + wget https://getcomposer.org/download/${COMPOSER_VERSION}/composer.phar && \ + php composer.phar install --no-dev --optimize-autoloader --no-progress --no-interaction && \ + php composer.phar clear-cache && \ + rm composer.phar + +# Add shlink to the path to ease running it after container is created +RUN ln -s /etc/shlink/bin/cli /usr/local/bin/shlink + +# Expose swoole port +EXPOSE 8080 + +# Expose params config dir, since the user is expected to provide custom config from there +VOLUME /etc/shlink/config/params + +# Copy config specific for the image +COPY docker/docker-entrypoint.sh docker-entrypoint.sh +COPY docker/config/shlink_in_docker.local.php config/autoload/shlink_in_docker.local.php + +ENTRYPOINT ["/bin/sh", "./docker-entrypoint.sh"] diff --git a/README.md b/README.md index 4ee6759b..932d0b7d 100644 --- a/README.md +++ b/README.md @@ -225,7 +225,7 @@ Right now, it does not import cached info (like website previews), but it will. ## Using a docker image -Starting with version 1.15.0, an official docker image is provided. You can find the docs on how to use it [here](https://hub.docker.com/r/shlinkio/shlink/). +Starting with version 1.15.0, an official docker image is provided. You can learn how to use it by reading [the docs](docker/README.md). The idea is that you can just generate a container using the image and provide custom config via env vars. diff --git a/build.sh b/build.sh index 7969b6aa..304a0ac9 100755 --- a/build.sh +++ b/build.sh @@ -19,7 +19,6 @@ mkdir -p "${builtcontent}" rsync -av * "${builtcontent}" \ --exclude=bin/test \ --exclude=data/infra \ - --exclude=data/travis \ --exclude=data/cache/* \ --exclude=data/log/* \ --exclude=data/locks/* \ @@ -33,8 +32,7 @@ rsync -av * "${builtcontent}" \ --exclude=composer.lock \ --exclude=vendor \ --exclude=docs \ - --exclude=indocker \ - --exclude=docker* \ + --exclude=*docker* \ --exclude=php* \ --exclude=infection.json \ --exclude=phpstan.neon \ diff --git a/composer.json b/composer.json index 994febcc..221c263a 100644 --- a/composer.json +++ b/composer.json @@ -102,7 +102,7 @@ "cs": "phpcs", "cs:fix": "phpcbf", - "stan": "phpstan analyse module/*/src/ module/*/config config --level=5 -c phpstan.neon", + "stan": "phpstan analyse module/*/src/ module/*/config config docker/config --level=5 -c phpstan.neon", "test": [ "@test:unit", diff --git a/data/travis/trigger_docker_build.sh b/data/travis/trigger_docker_build.sh deleted file mode 100644 index 565b30b5..00000000 --- a/data/travis/trigger_docker_build.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash -set -e - -# Get latest commit in master, in plain text -LATEST_MASTER_COMMIT=$(curl -H "Accept: application/vnd.github.sha" -X GET https://api.github.com/repos/shlinkio/shlink-docker-image/commits/master) - -# Create new tag and a ref to the tag, which will trigger image build on it -curl -u acelaya:${GITHUB_OAUTH_KEY} \ - -H "Content-Type: application/json" \ - --data "{ \"tag\": \"${TRAVIS_TAG}\", \"message\": \"${TRAVIS_TAG}\", \"object\": \"${LATEST_MASTER_COMMIT}\", \"type\": \"commit\" }" \ - -X POST https://api.github.com/repos/shlinkio/shlink-docker-image/git/tags -curl -u acelaya:${GITHUB_OAUTH_KEY} \ - -H "Content-Type: application/json" \ - --data "{ \"ref\": \"refs/tags/${TRAVIS_TAG}\", \"sha\": \"${LATEST_MASTER_COMMIT}\" }" \ - -X POST https://api.github.com/repos/shlinkio/shlink-docker-image/git/refs - -# Trigger image build for "latest -curl -H "Content-Type: application/json" \ - --data '{ "docker_tag": "latest" }' \ - -X POST https://registry.hub.docker.com/u/shlinkio/shlink/trigger/${DOCKER_TRIGGER_TOKEN}/ diff --git a/docker/README.md b/docker/README.md new file mode 100644 index 00000000..3f5601a1 --- /dev/null +++ b/docker/README.md @@ -0,0 +1,204 @@ +# Shlink Docker image + +[![Docker build status](https://img.shields.io/docker/cloud/build/shlinkio/shlink.svg?style=flat-square)](https://hub.docker.com/r/shlinkio/shlink/) +[![Docker pulls](https://img.shields.io/docker/pulls/shlinkio/shlink.svg?style=flat-square)](https://hub.docker.com/r/shlinkio/shlink/) + +This image provides an easy way to set up [shlink](https://shlink.io) on a container-based runtime. + +It exposes a shlink instance served with [swoole](https://www.swoole.co.uk/), which persists data in a local [sqlite](https://www.sqlite.org/index.html) database. + +## Usage + +Shlink docker image exposes port `8080` in order to interact with its HTTP interface. + +It also expects these two env vars to be provided, in order to properly generate short URLs at runtime. + +* `SHORT_DOMAIN_HOST`: The custom short domain used for this shlink instance. For example **doma.in**. +* `SHORT_DOMAIN_SCHEMA`: Either **http** or **https**. + +So based on this, to run shlink on a local docker service, you should run a command like this: + +```bash +docker run --name shlink -p 8080:8080 -e SHORT_DOMAIN_HOST=doma.in -e SHORT_DOMAIN_SCHEMA=https shlinkio/shlink +``` + +### Interact with shlink's CLI on a running container. + +Once the shlink container is running, you can interact with the CLI tool by running `shlink` with any of the supported commands. + +For example, if the container is called `shlink_container`, you can generate a new API key with: + +```bash +docker exec -it shlink_container shlink api-key:generate +``` + +Or you can list all tags with: + +```bash +docker exec -it shlink_container shlink tag:list +``` + +Or process remaining visits with: + +```bash +docker exec -it shlink_container shlink visit:process +``` + +All shlink commands will work the same way. + +You can also list all available commands just by running this: + +```bash +docker exec -it shlink_container shlink +``` + +## Use an external DB + +The image comes with a working sqlite database, but in production you will probably want to usa a distributed database. + +It is possible to use a set of env vars to make this shlink instance interact with an external MySQL or PostgreSQL database. + +* `DB_DRIVER`: **[Mandatory]**. Use the value **mysql** or **postgres** to prevent the sqlite database to be used. +* `DB_NAME`: [Optional]. The database name to be used. Defaults to **shlink**. +* `DB_USER`: **[Mandatory]**. The username credential for the database server. +* `DB_PASSWORD`: **[Mandatory]**. The password credential for the database server. +* `DB_HOST`: **[Mandatory]**. The host name of the server running the database engine. +* `DB_PORT`: [Optional]. The port in which the database service is running. + * Default value is based on the driver: + * **mysql** -> `3306` + * **postgres** -> `5432` + +> PostgreSQL is supported since v1.16.1 of this image. Do not try to use it with previous versions. + +Taking this into account, you could run shlink on a local docker service like this: + +```bash +docker run --name shlink -p 8080:8080 -e SHORT_DOMAIN_HOST=doma.in -e SHORT_DOMAIN_SCHEMA=https -e DB_DRIVER=mysql -e DB_USER=root -e DB_PASSWORD=123abc -e DB_HOST=something.rds.amazonaws.com shlinkio/shlink +``` + +You could even link to a local database running on a different container: + +```bash +docker run --name shlink -p 8080:8080 [...] -e DB_HOST=some_mysql_container --link some_mysql_container shlinkio/shlink +``` + +> If you have considered using SQLite but sharing the database file with a volume, read [this issue](https://github.com/shlinkio/shlink-docker-image/issues/40) first. + +## Supported env vars + +A few env vars have been already used in previous examples, but this image supports others that can be used to customize its behavior. + +This is the complete list of supported env vars: + +* `SHORT_DOMAIN_HOST`: The custom short domain used for this shlink instance. For example **doma.in**. +* `SHORT_DOMAIN_SCHEMA`: Either **http** or **https**. +* `SHORTCODE_CHARS`: A charset to use when building short codes. Only needed when using more than one shlink instance ([Multi instance considerations](#multi-instance-considerations)). +* `DB_DRIVER`: **sqlite** (which is the default value), **mysql** or **postgres**. +* `DB_NAME`: The database name to be used when using an external database driver. Defaults to **shlink**. +* `DB_USER`: The username credential to be used when using an external database driver. +* `DB_PASSWORD`: The password credential to be used when using an external database driver. +* `DB_HOST`: The host name of the database server when using an external database driver. +* `DB_PORT`: The port in which the database service is running when using an external database driver. Defaults to **3306**. +* `DISABLE_TRACK_PARAM`: The name of a query param that can be used to visit short URLs avoiding the visit to be tracked. This feature won't be available if not value is provided. +* `DELETE_SHORT_URL_THRESHOLD`: The amount of visits on short URLs which will not allow them to be deleted. Defaults to `15`. +* `LOCALE`: Defines the default language for error pages when a user accesses a short URL which does not exist. Supported values are **es** and **en**. Defaults to **en**. +* `VALIDATE_URLS`: Boolean which tells if shlink should validate a status 20x (after following redirects) is returned when trying to shorten a URL. Defaults to `true`. +* `NOT_FOUND_REDIRECT_TO`: If a URL is provided here, when a user tries to access an invalid short URL, he/she will be redirected to this value. If this env var is not provided, the user will see a generic `404 - not found` page. +* `REDIS_SERVERS`: A comma-separated list of redis servers where Shlink locks are stored (locks are used to prevent some operations to be run more than once in parallel). + + This is important when running more than one Shlink instance ([Multi instance considerations](#multi-instance-considerations)). If not provided, Shlink stores locks on every instance separately. + + If more than one server is provided, Shlink will expect them to be configured as a [redis cluster](https://redis.io/topics/cluster-tutorial). + + In the future, these redis servers could be used for other caching operations performed by shlink. + +An example using all env vars could look like this: + +```bash +docker run \ + --name shlink \ + -p 8080:8080 \ + -e SHORT_DOMAIN_HOST=doma.in \ + -e SHORT_DOMAIN_SCHEMA=https \ + -e DB_DRIVER=mysql \ + -e DB_NAME=shlink \ + -e DB_USER=root \ + -e DB_PASSWORD=123abc \ + -e DB_HOST=something.rds.amazonaws.com \ + -e DB_PORT=3306 \ + -e DISABLE_TRACK_PARAM="no-track" \ + -e DELETE_SHORT_URL_THRESHOLD=30 \ + -e LOCALE=es \ + -e VALIDATE_URLS=false \ + -e "NOT_FOUND_REDIRECT_TO=https://www.google.com" \ + -e "REDIS_SERVERS=tcp://172.20.0.1:6379,tcp://172.20.0.2:6379" \ + shlinkio/shlink +``` + +## Provide config via volumes + +Rather than providing custom configuration via env vars, it is also possible ot provide config files in json format. + +Mounting a volume at `config/params` you will make shlink load all the files on it with the `.config.json` suffix. + +The whole configuration should have this format, but it can be split into multiple files that will be merged: + +```json +{ + "disable_track_param": "my_param", + "delete_short_url_threshold": 30, + "locale": "es", + "short_domain_schema": "https", + "short_domain_host": "doma.in", + "validate_url": false, + "not_found_redirect_to": "https://my-landing-page.com", + "redis_servers": [ + "tcp://172.20.0.1:6379", + "tcp://172.20.0.2:6379" + ], + "db_config": { + "driver": "pdo_mysql", + "dbname": "shlink", + "user": "root", + "password": "123abc", + "host": "something.rds.amazonaws.com", + "port": "3306" + } +} +``` + +> This is internally parsed to how shlink expects the config. If you are using a version previous to 1.17.0, this parser is not present and you need to provide a config structure like the one [documented previously](https://github.com/shlinkio/shlink-docker-image/tree/v1.16.3#provide-config-via-volumes). + +Once created just run shlink with the volume: + +```bash +docker run --name shlink -p 8080:8080 -v ${PWD}/my/config/dir:/etc/shlink/config/params shlinkio/shlink +``` + +## Multi instance considerations + +These are some considerations to take into account when running multiple instances of shlink. + +* The first time shlink is run, it generates a charset used to generate short codes, which is a shuffled base62 charset. + + If you are using several shlink instances, you will probably want all of them to use the same charset. + + You can get a shuffled base62 charset by going to [https://shlink.io/short-code-chars](https://shlink.io/short-code-chars), and then you just need to pass it to all shlink instances using the `SHORTCODE_CHARS` env var. + + If you don't do this, each shlink instance will use a different charset. However this shouldn't be a problem in practice, since the chances to get a collision will be very low. + +* Some operations performed by Shlink should never be run more than once at the same time (like creating the database for the first time, or downloading the GeoLite2 database). For this reason, Shlink uses a locking system. + + However, these locks are locally scoped to each Shlink instance by default. + + You can (and should) make the locks to be shared by all Shlink instances by using a redis server/cluster. Just define the `REDIS_SERVERS` env var with the list of servers. + +## Versions + +Versions of this image match the shlink version it contains. + +For example, installing `shlinkio/shlink:1.15.0`, you will get an image containing shlink v1.15.0. + +The `latest` docker tag always holds the latest contents in master, and it's considered unestable and not suitable for production. + +> There are no official shlink images previous to v1.15.0. diff --git a/docker/config/shlink_in_docker.local.php b/docker/config/shlink_in_docker.local.php new file mode 100644 index 00000000..37870c9b --- /dev/null +++ b/docker/config/shlink_in_docker.local.php @@ -0,0 +1,175 @@ + 'pdo_mysql', + 'postgres' => 'pdo_pgsql', + ]; + private const DB_PORTS_MAP = [ + 'mysql' => '3306', + 'postgres' => '5432', + ]; + + /** @var string */ + private $charset; + /** @var string */ + private $secretKey; + + public function __construct() + { + [$this->charset, $this->secretKey] = $this->initShlinkKeys(); + } + + private function initShlinkKeys(): array + { + $keysFile = sprintf('%s/shlink.keys', sys_get_temp_dir()); + if (file_exists($keysFile)) { + return explode(',', file_get_contents($keysFile)); + } + + $keys = [ + env('SHORTCODE_CHARS', $this->generateShortcodeChars()), + env('SECRET_KEY', $this->generateSecretKey()), + ]; + + file_put_contents($keysFile, implode(',', $keys)); + return $keys; + } + + private function generateShortcodeChars(): string + { + return str_shuffle(self::BASE62); + } + + private function generateSecretKey(): string + { + return substr(str_shuffle(self::BASE62), 0, 32); + } + + public function getShortcodeChars(): string + { + return $this->charset; + } + + public function getSecretKey(): string + { + return $this->secretKey; + } + + public function getDbConfig(): array + { + $driver = env('DB_DRIVER'); + if ($driver === null || $driver === 'sqlite') { + return [ + 'driver' => 'pdo_sqlite', + 'path' => 'data/database.sqlite', + ]; + } + + $driverOptions = $driver !== 'mysql' ? [] : [ + // PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8', + 1002 => 'SET NAMES utf8', + ]; + return [ + 'driver' => self::DB_DRIVERS_MAP[$driver], + 'dbname' => env('DB_NAME', 'shlink'), + 'user' => env('DB_USER'), + 'password' => env('DB_PASSWORD'), + 'host' => env('DB_HOST'), + 'port' => env('DB_PORT', self::DB_PORTS_MAP[$driver]), + 'driverOptions' => $driverOptions, + ]; + } + + public function getNotFoundConfig(): array + { + $notFoundRedirectTo = env('NOT_FOUND_REDIRECT_TO'); + + return [ + 'enable_redirection' => $notFoundRedirectTo !== null, + 'redirect_to' => $notFoundRedirectTo, + ]; + } +}; + +return [ + + 'config_cache_enabled' => false, + + 'app_options' => [ + 'secret_key' => $helper->getSecretKey(), + 'disable_track_param' => env('DISABLE_TRACK_PARAM'), + ], + + 'delete_short_urls' => [ + 'check_visits_threshold' => true, + 'visits_threshold' => (int) env('DELETE_SHORT_URL_THRESHOLD', 15), + ], + + 'translator' => [ + 'locale' => env('LOCALE', 'en'), + ], + + 'entity_manager' => [ + 'connection' => $helper->getDbConfig(), + ], + + 'url_shortener' => [ + 'domain' => [ + 'schema' => env('SHORT_DOMAIN_SCHEMA', 'http'), + 'hostname' => env('SHORT_DOMAIN_HOST', ''), + ], + 'shortcode_chars' => $helper->getShortcodeChars(), + 'validate_url' => (bool) env('VALIDATE_URLS', true), + 'not_found_short_url' => $helper->getNotFoundConfig(), + ], + + 'logger' => [ + 'handlers' => [ + 'shlink_rotating_handler' => [ + 'level' => Logger::EMERGENCY, // This basically disables regular file logs + ], + 'shlink_stdout_handler' => [ + 'class' => StreamHandler::class, + 'level' => Logger::INFO, + 'stream' => 'php://stdout', + 'formatter' => 'dashed', + ], + ], + + 'loggers' => [ + 'Shlink' => [ + 'handlers' => ['shlink_stdout_handler'], + ], + ], + ], + + 'dependencies' => [ + 'aliases' => env('REDIS_SERVERS') === null ? [] : [ + 'lock_store' => 'redis_lock_store', + ], + ], + + 'redis' => [ + 'servers' => env('REDIS_SERVERS'), + ], + +]; diff --git a/docker/docker-entrypoint.sh b/docker/docker-entrypoint.sh new file mode 100644 index 00000000..4842522d --- /dev/null +++ b/docker/docker-entrypoint.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env sh +set -e + +cd /etc/shlink + +echo "Creating fresh database if needed..." +php bin/cli db:create -n -q + +echo "Updating database..." +php bin/cli db:migrate -n -q + +echo "Generating proxies..." +php vendor/doctrine/orm/bin/doctrine.php orm:generate-proxies -n -q + +# When restarting the container, swoole might think it is already in execution +# This forces the app to be started every second until the exit code is 0 +until php vendor/zendframework/zend-expressive-swoole/bin/zend-expressive-swoole start; do sleep 1 ; done diff --git a/phpcs.xml b/phpcs.xml index 407ae5bd..b79d7b40 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -14,6 +14,7 @@ module data/migrations config + docker/config public/index.php From b927e441070b0c511e55b18beb257394ee0c0afc Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Fri, 16 Aug 2019 18:55:35 +0200 Subject: [PATCH 2/8] Ensured all composer-related files are deleted from docker image --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 0c8be534..f122b062 100644 --- a/Dockerfile +++ b/Dockerfile @@ -35,7 +35,7 @@ RUN rm -rf ./docker && \ wget https://getcomposer.org/download/${COMPOSER_VERSION}/composer.phar && \ php composer.phar install --no-dev --optimize-autoloader --no-progress --no-interaction && \ php composer.phar clear-cache && \ - rm composer.phar + rm composer.* # Add shlink to the path to ease running it after container is created RUN ln -s /etc/shlink/bin/cli /usr/local/bin/shlink From 57c0490d844b5c65421808f6da67e4dbeb48a531 Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Fri, 16 Aug 2019 19:13:35 +0200 Subject: [PATCH 3/8] Updated travis config to test docker image building when the dockerfile has changed --- .travis.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e63a202d..9858a106 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,6 +16,7 @@ matrix: services: - mysql - postgresql + - docker before_install: - echo 'extension = apcu.so' >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini @@ -30,9 +31,11 @@ before_script: - mysql -e 'CREATE DATABASE shlink_test;' - psql -c 'create database shlink_test;' -U postgres - mkdir build + - export DOCKERFILE_CHANGED=$(git diff ${TRAVIS_COMMIT_RANGE:-origin/master} --name-only | grep Dockerfile) script: - composer ci + - [[ ! -z "$DOCKERFILE_CHANGED" ]] && docker build -t shlink-docker-image:temp . after_success: - rm -f build/clover.xml @@ -53,4 +56,4 @@ deploy: skip_cleanup: true on: tags: true - php: 7.2 + php: '7.2' From 65d13011959635f1f6a70ba1091104ed49e9e254 Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Fri, 16 Aug 2019 19:30:40 +0200 Subject: [PATCH 4/8] Simplified build script to exclude everything from dockerignore for rsync --- Dockerfile | 2 +- build.sh | 27 +++------------------------ 2 files changed, 4 insertions(+), 25 deletions(-) diff --git a/Dockerfile b/Dockerfile index f122b062..0d3cc037 100644 --- a/Dockerfile +++ b/Dockerfile @@ -24,7 +24,7 @@ RUN \ # Install swoole # First line fixes an error when installing pecl extensions. Found in https://github.com/docker-library/php/issues/233 -RUN apk add --no-cache --virtual .phpize-deps $PHPIZE_DEPS && \ +RUN apk add --no-cache --virtual .phpize-deps ${PHPIZE_DEPS} && \ pecl install swoole-${SWOOLE_VERSION} && \ docker-php-ext-enable swoole && \ apk del .phpize-deps diff --git a/build.sh b/build.sh index 304a0ac9..cf42695b 100755 --- a/build.sh +++ b/build.sh @@ -17,36 +17,15 @@ echo 'Copying project files...' rm -rf "${builtcontent}" mkdir -p "${builtcontent}" rsync -av * "${builtcontent}" \ - --exclude=bin/test \ - --exclude=data/infra \ - --exclude=data/cache/* \ - --exclude=data/log/* \ - --exclude=data/locks/* \ - --exclude=data/proxies/* \ - --exclude=data/migrations_template.txt \ - --exclude=data/GeoLite2-City.* \ - --exclude=data/database.sqlite \ - --exclude=data/shlink-tests.db \ - --exclude=**/.gitignore \ - --exclude=CHANGELOG.md \ - --exclude=composer.lock \ - --exclude=vendor \ - --exclude=docs \ --exclude=*docker* \ - --exclude=php* \ - --exclude=infection.json \ - --exclude=phpstan.neon \ - --exclude=config/autoload/*local* \ - --exclude=config/test \ - --exclude=**/test* \ - --exclude=build* \ - --exclude=.github + --exclude=Dockerfile \ + --exclude-from=./.dockerignore cd "${builtcontent}" # Install dependencies echo "Installing dependencies with $composerBin..." ${composerBin} self-update -${composerBin} install --no-dev --optimize-autoloader --apcu-autoloader --no-progress --no-interaction +${composerBin} install --no-dev --optimize-autoloader --no-progress --no-interaction # Delete development files echo 'Deleting dev files...' From 924383ccc8106a3c3a1614c249d4b1ce8e9f8513 Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Fri, 16 Aug 2019 19:42:39 +0200 Subject: [PATCH 5/8] Updated docker image build so that it sets shlink's version --- .dockerignore | 1 + .gitignore | 1 + Dockerfile | 3 +++ hooks/build | 10 ++++++++++ 4 files changed, 15 insertions(+) create mode 100755 hooks/build diff --git a/.dockerignore b/.dockerignore index 56849556..7c730c69 100644 --- a/.dockerignore +++ b/.dockerignore @@ -21,3 +21,4 @@ phpstan.neon **/test* build* .github +hooks diff --git a/.gitignore b/.gitignore index f01b1741..7b14364c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ .idea build +!hooks/build composer.lock composer.phar vendor/ diff --git a/Dockerfile b/Dockerfile index 0d3cc037..829be575 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,8 @@ FROM php:7.3.8-cli-alpine3.10 LABEL maintainer="Alejandro Celaya " +ARG SHLINK_VERSION=1.18.1 +ENV SHLINK_VERSION ${SHLINK_VERSION} ENV SWOOLE_VERSION 4.3.3 ENV COMPOSER_VERSION 1.9.0 @@ -39,6 +41,7 @@ RUN rm -rf ./docker && \ # Add shlink to the path to ease running it after container is created RUN ln -s /etc/shlink/bin/cli /usr/local/bin/shlink +RUN sed -i "s/%SHLINK_VERSION%/${SHLINK_VERSION}/g" config/autoload/app_options.global.php # Expose swoole port EXPOSE 8080 diff --git a/hooks/build b/hooks/build new file mode 100755 index 00000000..efabd3d7 --- /dev/null +++ b/hooks/build @@ -0,0 +1,10 @@ +#!/bin/bash +set -ex + +if [[ ${SOURCE_BRANCH} == 'master' ]]; then + SHLINK_RELEASE='latest' +else + SHLINK_RELEASE=${SOURCE_BRANCH} +fi + +docker build --build-arg SHLINK_VERSION=${SHLINK_RELEASE#?} -t ${IMAGE_NAME} . From cb7a66c59bdb23515dd48d731621f2075ab421f1 Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Fri, 16 Aug 2019 19:48:23 +0200 Subject: [PATCH 6/8] Updated changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2954b213..df5bbca1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com), and this * [#450](https://github.com/shlinkio/shlink/issues/450) Added PHP 7.4 to the build matrix, as an allowed-to-fail env. * [#441](https://github.com/shlinkio/shlink/issues/441) and [#443](https://github.com/shlinkio/shlink/issues/443) Split some logic into independent modules. * [#451](https://github.com/shlinkio/shlink/issues/451) Updated to infection 0.13. +* [#467](https://github.com/shlinkio/shlink/issues/467) Moved docker image config to this repo. #### Deprecated @@ -22,7 +23,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com), and this #### Removed -* *Nothing* +* [#468](https://github.com/shlinkio/shlink/issues/468) Removed APCu extension from docker image. #### Fixed From 872241f49700256ad8ae19bca1fd7704915385c7 Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Fri, 16 Aug 2019 20:27:04 +0200 Subject: [PATCH 7/8] Fixed travis config using invalid structure --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 9858a106..837884e7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -35,7 +35,7 @@ before_script: script: - composer ci - - [[ ! -z "$DOCKERFILE_CHANGED" ]] && docker build -t shlink-docker-image:temp . + - if [[ ! -z "$DOCKERFILE_CHANGED" ]]; then docker build -t shlink-docker-image:temp . ; fi after_success: - rm -f build/clover.xml From 209e3e9e14b9819dcb7817e9af0ad5c8556b9785 Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Fri, 16 Aug 2019 20:49:24 +0200 Subject: [PATCH 8/8] Updated travis to only build docker image in one of the envs --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 837884e7..5e0b9c65 100644 --- a/.travis.yml +++ b/.travis.yml @@ -35,7 +35,7 @@ before_script: script: - composer ci - - if [[ ! -z "$DOCKERFILE_CHANGED" ]]; then docker build -t shlink-docker-image:temp . ; fi + - if [[ ! -z "$DOCKERFILE_CHANGED" && "${TRAVIS_PHP_VERSION}" == "7.2" ]]; then docker build -t shlink-docker-image:temp . ; fi after_success: - rm -f build/clover.xml