Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.git
.DS_Store
.vscode
stage
include/ost-config.php
include/mpdf/tmp
include/mpdf/ttfontdata
8 changes: 8 additions & 0 deletions .env.docker.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
OSTICKET_HTTP_PORT=8080
OSTICKET_DEPLOY_ON_START=1
OSTICKET_DEFAULT_LANG=pt_BR
MYSQL_DATABASE=osticket
MYSQL_USER=osticket
MYSQL_PASSWORD=osticket
MYSQL_ROOT_PASSWORD=root
TZ=America/Sao_Paulo
62 changes: 62 additions & 0 deletions .github/workflows/publish-image.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
name: Publish Docker Image

on:
push:
branches:
- '**'
tags:
- 'v*'
pull_request:
workflow_dispatch:

concurrency:
group: publish-image-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read
packages: write

jobs:
docker:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up QEMU
uses: docker/setup-qemu-action@v3

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to GHCR
if: github.event_name != 'pull_request'
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository }}
tags: |
type=ref,event=branch
type=ref,event=tag
type=sha,prefix=sha-
type=raw,value=latest,enable={{is_default_branch}}

- name: Build and publish image
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
platforms: linux/amd64,linux/arm64
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ stage
include/mpdf/ttfontdata
include/mpdf/tmp
nbproject/
.env.docker
52 changes: 52 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
FROM php:8.3-apache-bookworm

ENV APACHE_DOCUMENT_ROOT=/var/www/html \
OSTICKET_APP=/var/www/html \
OSTICKET_SRC=/srv/osticket-src

RUN apt-get update \
&& apt-get install -y --no-install-recommends \
git \
libc-client2007e-dev \
libfreetype6-dev \
libicu-dev \
libjpeg62-turbo-dev \
libkrb5-dev \
libpng-dev \
libxml2-dev \
libzip-dev \
&& docker-php-source extract \
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
&& ac_cv_utf8_mime2text=new ac_cv_u8t_decompose=yes docker-php-ext-configure imap --with-kerberos --with-imap-ssl \
&& docker-php-ext-install -j"$(nproc)" \
gd \
gettext \
imap \
intl \
mysqli \
opcache \
zip \
&& pecl install apcu \
&& docker-php-ext-enable apcu \
&& docker-php-source delete \
&& a2enmod expires headers rewrite \
&& sed -ri "s!/var/www/html!${APACHE_DOCUMENT_ROOT}!g" \
/etc/apache2/apache2.conf \
/etc/apache2/conf-available/*.conf \
/etc/apache2/sites-available/*.conf \
&& rm -rf /var/lib/apt/lists/*

COPY . /srv/osticket-src
COPY docker/i18n/ /opt/osticket-i18n/
COPY docker/apache/osticket.conf /etc/apache2/conf-available/osticket.conf
COPY docker/php/osticket.ini /usr/local/etc/php/conf.d/osticket.ini
COPY docker/entrypoint.sh /usr/local/bin/osticket-entrypoint

RUN chmod +x /usr/local/bin/osticket-entrypoint \
&& a2enconf osticket \
&& mkdir -p /var/www/html

WORKDIR /var/www/html

ENTRYPOINT ["osticket-entrypoint"]
CMD ["apache2-foreground"]
54 changes: 54 additions & 0 deletions README.docker.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# osTicket com Docker

Este repositório agora inclui um ambiente local com `docker compose` para subir o osTicket com `PHP 8.4 + Apache` e `MariaDB 10.11`.

## Como subir

1. Copie o arquivo de exemplo:

```bash
cp .env.docker.example .env.docker
```

2. Suba os containers:

```bash
docker compose --env-file .env.docker up --build
```

3. Abra:

```text
http://localhost:8080/setup/
```

## Banco para o instalador

Use os valores abaixo no instalador web, a menos que tenha alterado o `.env.docker`:

- Host: `db`
- Database: `osticket`
- User: `osticket`
- Password: `osticket`

## Como funciona

- O container `web` instala as extensoes PHP exigidas pelo projeto, incluindo `imap`.
- O container tambem habilita `APCu` para melhorar cache e desempenho.
- No startup, o entrypoint executa `php manage.php deploy --setup /var/www/html`.
- O codigo-fonte local e montado em `/srv/osticket-src` apenas para servir de origem ao `deploy`.
- O deploy final fica persistido no volume `osticket-app`.
- O banco fica persistido no volume `osticket-db`.

## Atualizando o codigo

Por padrao, o container reaplica o `deploy` a cada start com `OSTICKET_DEPLOY_ON_START=1`. Se quiser desligar esse comportamento, ajuste a variavel no `.env.docker`.

## Pos-instalacao

Depois que a instalacao terminar, vale remover a pasta `setup` do volume implantado e travar o arquivo de configuracao:

```bash
docker compose exec web rm -rf /var/www/html/setup
docker compose exec web chmod 0644 /var/www/html/include/ost-config.php
```
49 changes: 49 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
services:
web:
build:
context: .
depends_on:
db:
condition: service_healthy
environment:
OSTICKET_APP: /var/www/html
OSTICKET_DB_HOST: ${OSTICKET_DB_HOST:-db}
OSTICKET_DB_NAME: ${MYSQL_DATABASE:-osticket}
OSTICKET_DB_PASS: ${MYSQL_PASSWORD:-osticket}
OSTICKET_DB_PREFIX: ${OSTICKET_DB_PREFIX:-ost_}
OSTICKET_DB_USER: ${MYSQL_USER:-osticket}
OSTICKET_DEFAULT_LANG: ${OSTICKET_DEFAULT_LANG:-pt_BR}
OSTICKET_DEPLOY_ON_START: ${OSTICKET_DEPLOY_ON_START:-1}
OSTICKET_SRC: /srv/osticket-src
TZ: ${TZ:-America/Sao_Paulo}
ports:
- "${OSTICKET_HTTP_PORT:-8080}:80"
volumes:
- .:/srv/osticket-src:ro
- osticket-app:/var/www/html
restart: unless-stopped

db:
image: mariadb:10.11
command:
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
environment:
MYSQL_DATABASE: ${MYSQL_DATABASE:-osticket}
MYSQL_PASSWORD: ${MYSQL_PASSWORD:-osticket}
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-root}
MYSQL_USER: ${MYSQL_USER:-osticket}
TZ: ${TZ:-America/Sao_Paulo}
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
interval: 10s
timeout: 5s
retries: 10
start_period: 20s
restart: unless-stopped
volumes:
- osticket-db:/var/lib/mysql

volumes:
osticket-app:
osticket-db:
5 changes: 5 additions & 0 deletions docker/apache/osticket.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<Directory /var/www/html>
AllowOverride All
Options FollowSymLinks
Require all granted
</Directory>
93 changes: 93 additions & 0 deletions docker/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#!/bin/sh
set -eu

OSTICKET_APP="${OSTICKET_APP:-/var/www/html}"
OSTICKET_SRC="${OSTICKET_SRC:-/srv/osticket-src}"
OSTICKET_DEPLOY_ON_START="${OSTICKET_DEPLOY_ON_START:-1}"
OSTICKET_CONFIG="${OSTICKET_APP}/include/ost-config.php"
OSTICKET_I18N_SRC="${OSTICKET_I18N_SRC:-/opt/osticket-i18n}"
OSTICKET_SAMPLE_CONFIG="${OSTICKET_APP}/include/ost-sampleconfig.php"
OSTICKET_SETUP_DIR="${OSTICKET_APP}/setup"

deploy_osticket() {
if [ ! -f "${OSTICKET_SRC}/manage.php" ]; then
echo "osTicket source not found at ${OSTICKET_SRC}" >&2
exit 1
fi

git config --global --add safe.directory "${OSTICKET_SRC}" >/dev/null 2>&1 || true

mkdir -p "${OSTICKET_APP}"
(
cd "${OSTICKET_SRC}"
php manage.php deploy --setup "${OSTICKET_APP}"
)
}

prepare_config() {
if [ ! -f "${OSTICKET_CONFIG}" ] && [ -f "${OSTICKET_SAMPLE_CONFIG}" ]; then
cp "${OSTICKET_SAMPLE_CONFIG}" "${OSTICKET_CONFIG}"
fi

if [ -f "${OSTICKET_CONFIG}" ]; then
if grep -q "%CONFIG-DBHOST" "${OSTICKET_CONFIG}"; then
chmod 0666 "${OSTICKET_CONFIG}"
else
chmod 0644 "${OSTICKET_CONFIG}"
fi
fi
}

prepare_runtime_dirs() {
mkdir -p \
"${OSTICKET_APP}/include/i18n" \
"${OSTICKET_APP}/include/mpdf/tmp" \
"${OSTICKET_APP}/include/mpdf/ttfontdata"
chown -R www-data:www-data "${OSTICKET_APP}"
}

install_language_packs() {
if [ -d "${OSTICKET_I18N_SRC}" ]; then
find "${OSTICKET_I18N_SRC}" -maxdepth 1 -type f -name '*.phar' -exec cp {} "${OSTICKET_APP}/include/i18n/" \;
fi
}

installation_complete() {
[ -f "${OSTICKET_CONFIG}" ] \
&& ! grep -q "define('OSTINSTALLED',FALSE);" "${OSTICKET_CONFIG}" 2>/dev/null
}

finalize_installation() {
chmod 0644 "${OSTICKET_CONFIG}" 2>/dev/null || true
rm -rf "${OSTICKET_SETUP_DIR}" 2>/dev/null || true
}

finalize_after_install() {
(
while [ ! -f "${OSTICKET_CONFIG}" ]; do
sleep 2
done

while ! installation_complete; do
sleep 2
done

finalize_installation
Comment on lines +71 to +75
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Delay removing setup until the install request has finished

In the Docker install flow, this background watcher removes ${OSTICKET_SETUP_DIR} as soon as ost-config.php flips to installed. The same POST to /setup/install.php still needs files under setup/ after that point: after Installer::install() rewrites the config, setup/install.php selects install-done.inc.php and then requires the setup header/body/footer. On slower fresh installs, if the watcher wakes between the config rewrite and those final require() calls, it can delete the directory out from under the active request and turn a successful install into a 500/blank response. Wait for the request to complete or perform this cleanup on the next container start/manual step instead of immediately in the background.

Useful? React with 👍 / 👎.

) &
}

if [ ! -f "${OSTICKET_APP}/index.php" ] || [ "${OSTICKET_DEPLOY_ON_START}" = "1" ]; then
deploy_osticket
fi

prepare_config
prepare_runtime_dirs
install_language_packs

if installation_complete; then
finalize_installation
else
finalize_after_install
fi

exec "$@"
Binary file added docker/i18n/pt_BR.phar
Binary file not shown.
6 changes: 6 additions & 0 deletions docker/php/osticket.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
date.timezone=America/Sao_Paulo
file_uploads=On
max_execution_time=120
memory_limit=256M
post_max_size=32M
upload_max_filesize=32M
14 changes: 13 additions & 1 deletion setup/inc/install.inc.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
<?php
if(!defined('SETUPINC')) die('Kwaheri!');
$info=($_POST && $errors)?Format::htmlchars($_POST):array('prefix'=>'ost_','dbhost'=>'localhost','lang_id'=>'en_US');

$defaults = array(
'prefix' => getenv('OSTICKET_DB_PREFIX') ?: 'ost_',
'dbhost' => getenv('OSTICKET_DB_HOST') ?: 'localhost',
'dbname' => getenv('OSTICKET_DB_NAME') ?: '',
'dbuser' => getenv('OSTICKET_DB_USER') ?: '',
'dbpass' => getenv('OSTICKET_DB_PASS') ?: '',
'lang_id' => getenv('OSTICKET_DEFAULT_LANG') ?: 'en_US',
);

$info = ($_POST && $errors)
? Format::htmlchars($_POST)
: $defaults;
?>
<div id="main" class="step2">
<h1><?php echo __('osTicket Basic Installation'); ?></h1>
Expand Down
Loading