diff --git a/.github/images/embt-logo-black.png b/.github/images/embt-logo-black.png
new file mode 100644
index 0000000..257833a
Binary files /dev/null and b/.github/images/embt-logo-black.png differ
diff --git a/.github/images/embt-logo-white.png b/.github/images/embt-logo-white.png
new file mode 100644
index 0000000..500cf98
Binary files /dev/null and b/.github/images/embt-logo-white.png differ
diff --git a/.github/images/rad-studio-logo.png b/.github/images/rad-studio-logo.png
new file mode 100644
index 0000000..20885af
Binary files /dev/null and b/.github/images/rad-studio-logo.png differ
diff --git a/Dockerfile b/Dockerfile
index 25cad79..96a64bb 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,39 +1,57 @@
-FROM ubuntu:jammy
-# jammy is the code name of 22.04 LTS
+# Build Stage
+FROM ubuntu:jammy as builder
-ARG password=embtdocker
+ARG password=securepass
ENV PA_SERVER_PASSWORD=$password
+ENV PA_SERVER_URL=https://altd.embarcadero.com/releases/studio/23.0/121/1211/LinuxPAServer23.0.tar.gz
+ENV PA_SERVER_VERSION=23.0
+
+# Install build dependencies
+RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -yy --no-install-recommends \
+ curl \
+ && rm -rf /var/lib/apt/lists/*
+
+# Download and extract PAServer
+RUN curl -L "${PA_SERVER_URL}" -k -o ./paserver.tar.gz \
+ && tar xvzf paserver.tar.gz \
+ && mkdir /paserver \
+ && mv PAServer-${PA_SERVER_VERSION}/* /paserver \
+ && rm -rf PAServer-${PA_SERVER_VERSION} paserver.tar.gz
+
+# Runtime Stage
+FROM ubuntu:jammy
-RUN apt-get update && \
- DEBIAN_FRONTEND=noninteractive apt-get -yy install \
+# Install runtime dependencies
+RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -yy --no-install-recommends \
joe \
- wget \
- p7zip-full \
curl \
- openssh-server \
build-essential \
+ p7zip-full \
+ openssh-server \
zlib1g-dev \
libcurl4-gnutls-dev \
libncurses5 \
- libpython3.10
-
-### Install PAServer
-ADD https://altd.embarcadero.com/releases/studio/23.0/121/1211/LinuxPAServer23.0.tar.gz ./paserver.tar.gz
+ libpython3.10 \
+ && rm -rf /var/lib/apt/lists/*
-RUN tar xvzf paserver.tar.gz
-RUN mv PAServer-23.0/* .
-RUN rm PAServer-23.0 -r
-RUN rm paserver.tar.gz
+# Copy PAServer and the runner script from the builder stage
+COPY --from=builder /paserver /paserver
+COPY paserver_docker.sh /paserver/paserver_docker.sh
-# link to installed libpython3.10
-RUN mv lldb/lib/libpython3.so lldb/lib/libpython3.so_
-RUN ln -s /lib/x86_64-linux-gnu/libpython3.10.so.1 lldb/lib/libpython3.so
+# Set work directory
+WORKDIR /paserver
-COPY paserver_docker.sh ./paserver_docker.sh
-RUN chmod +x paserver_docker.sh
+# Creates the symlink to the Python interpreter in the PAServer required location and grant execution permission to the runner script
+RUN mv lldb/lib/libpython3.so lldb/lib/libpython3.so_ \
+ && ln -s /lib/x86_64-linux-gnu/libpython3.10.so.1 lldb/lib/libpython3.so \
+ && chmod +x ./paserver_docker.sh
-# PAServer
+# Expose PAServer's default port
EXPOSE 64211
-CMD ./paserver_docker.sh
+# Get ready to bind to PAServer's default scratch dir
+VOLUME ["/root/PAServer/scratch-dir"]
+
+# Executes PAServer runner script
+ENTRYPOINT ["./paserver_docker.sh"]
\ No newline at end of file
diff --git a/README.md b/README.md
index 4d3b228..329b09e 100644
--- a/README.md
+++ b/README.md
@@ -1,48 +1,253 @@
-# paserver-docker
-
-Docker script for RAD Studio Linux deployment via PAServer
+# RAD Studio PAServer Docker
-- **Container available on [Docker Hub](https://hub.docker.com/r/radstudio/pa-radserver)**
-- [PAServer Documentation](http://docwiki.embarcadero.com/RADStudio/en/PAServer,_the_Platform_Assistant_Server_Application)
-- [More information on RAD Studio](https://www.embarcadero.com/products/rad-studio)
-- Other containers: [InterBase](https://github.com/Embarcadero/InterBase-Docker) only, [RAD Server](https://github.com/Embarcadero/pa-radserver-docker), and [RAD Server with InterBase](https://github.com/Embarcadero/pa-radserver-ib-docker)
+
+
+Welcome to the guide for deploying RAD Studio applications on Linux using Docker and PAServer. This repository offers a Docker script designed to simplify the setup and management of your development environment, allowing RAD Studio developers to deploy and test their applications in a Linux environment.
+
+- **Container available on [Docker Hub][dockerhub-paserver]**
+- [PAServer Documentation][paserver-docs]
+- [More information on RAD Studio][radstudio]
+- Other containers: [InterBase][github-interbase-docker] only, [RAD Server][github-radserver-docker], and [RAD Server with InterBase][github-radserver-interbase-docker]
The image defaults to running **PAServer** on port `64211` with the _password_ `securepass`
-The 10.x images use Ubuntu 18.04.6 LTS (Bionic Beaver) while the 11.x images use Ubuntu 22.04.1 LTS (Jammy Jellyfish)
+The 10.x images use Ubuntu 18.04.6 LTS (Bionic Beaver) while the +11.x images use Ubuntu 22.04.1 LTS (Jammy Jellyfish)
+
+## 🚀 How to Use [`run.sh`] Script
+
+The [`run.sh`] script is your go-to automation tool for setting up and deploying the PAServer application with ease and flexibility. Below are the instructions to utilize this script effectively.
+
+### 📋 Prerequisites
+
+Ensure Docker is installed on your system as this script uses Docker for running the PAServer application.
+
+### 🌟 Features
+
+- **Customizable Name**: Assign a unique name to your PAServer container.
+- **Bind Path**: Designate a custom path for volume mapping.
+- **Detach Mode**: Opt for running your container in the background.
+- **Port Configuration**: Select the port where PAServer runs.
+- **Production Mode**: Activate production mode for your deployment.
+- **Version Control**: Choose the specific PAServer version for deployment.
+- **Password Protection**: Secure your PAServer with a custom password.
+
+### 🛠️ Usage
+
+Navigate to the directory containing [`run.sh`] in your terminal. Execute the script with your preferred options:
+
+```bash
+./run.sh [OPTIONS]
+```
+
+#### 📌 Options
+
+- `--name` or `-n`: Container's name (e.g., `--name=myPAServer`).
+- `--path` or `-pa`: Bind path for volume mapping (e.g., `--path=/my/custom/path`).
+- `--detach` or `-d`: Run container in detach mode (background).
+- `--port` or `-p`: Port for PAServer (e.g., `--port=64211`).
+- `--production` or `-pr`: Enable production mode (`true`).
+- `--version` or `-v`: PAServer version (e.g., `--version=latest`).
+- `--password` or `-pw`: Set a password for PAServer (e.g., `--password=securepass`).
+- `--help` or `-h`: Shows the help of the script.
+
+### 🌈 Examples
+
+Run PAServer in production mode on port 65000 with a custom name and password:
+
+```bash
+./run.sh --name=myPAServer --port=65000 --production --password=mysupersecurepassword
+```
+
+Run PAServer in detach mode with a specific version, bind path, and password:
-## Instructions
+```bash
+./run.sh --detach --version=12.1 --path=/my/custom/path --password=mysupersecurepassword
+```
+
+### 📝 Note
+
+Make sure you have the necessary permissions to execute `run.sh`. Use `chmod +x run.sh` to make it executable if needed.
+
+## 🐳 Using `docker run` Directly
+
+For users who prefer a more hands-on approach or wish to customize their deployment further, you can directly use the `docker run` command to start your PAServer container. This method provides flexibility and allows you to manually specify each option.
-If you want to modify or build from GitHub without using [Docker Hub](https://hub.docker.com/r/radstudio/pa-radserver), you can build the Dockerfile with the `build.sh` script. **Note:** The Dockerfile requires the `paserver_docker.sh` script in the same directory
+### 🛠️ Command Structure
+
+The basic structure of the command to run the PAServer Docker container is as follows:
+
+```bash
+docker run [OPTIONS] radstudio/paserver:[VERSION]
```
-./build.sh
+
+### 📌 Options
+
+- `-e PA_SERVER_PASSWORD=[PASSWORD]`: Sets the password for the PAServer. Replace `[PASSWORD]` with your desired password.
+- `--name [NAME]`: Assigns a custom name to your Docker container. Replace `[NAME]` with your preferred container name.
+- `-p [PORT]:64211`: Maps a custom port on your host to the PAServer's default port (64211). Replace `[PORT]` with the port number you wish to use.
+- `[DETACH_ARG]`: Use `-d` to run the container in detached mode (in the background).
+- `[BIND_PATH_ARG]`: Use `-v [HOST_PATH]:[CONTAINER_PATH]` to bind a volume for persistent data or configurations. Replace `[HOST_PATH]` and `[CONTAINER_PATH]` with your specific paths.
+
+### 🌈 Examples
+
+To run the PAServer in a Docker container named `myPAServer`, listening on port 65000, with a password of `mysupersecurepassword`, and running in detached mode, you would use the following command:
+
+```bash
+docker run -d \
+ -e PA_SERVER_PASSWORD=mysupersecurepassword \
+ --name myPAServer \
+ -p 65000:64211 radstudio/paserver:latest
+```
+
+If you wish to bind a volume for persistent data, you can add the `-v` option:
+
+```bash
+docker run -d \
+ -e PA_SERVER_PASSWORD=securepass \
+ -v /path/on/host:/root/PAServer/scratch-dir \
+ --name myPAServer \
+ -p 65000:64211 radstudio/paserver:latest
+```
+
+#### Using Docker Compose
+
+Docker Compose allows you to define and run multi-container Docker applications. Here is an example `docker-compose.yml` file that demonstrates how to use a Docker image as part of a service, utilizing environment variables for configuration.
+
+```yaml
+version: '3.8'
+services:
+ myPAServer:
+ image: radstudio/paserver:latest
+ container_name: myPAServer
+ environment:
+ - PA_SERVER_PASSWORD=${PA_SERVER_PASSWORD} # Environment variable for the server password
+ ports:
+ - '${HOST_PORT}:64211' # Environment variable for the host port
+ volumes:
+ - ${HOST_PATH}:/root/PAServer/scratch-dir # Environment variable for the host path
+ restart: unless-stopped
```
-To pull and run the [Docker Hub](https://hub.docker.com/r/radstudio/paserver) version of PAServer Docker for a debug/non-production environment use the `pull-run.sh` script
+This configuration defines a single service called `myPAServer`. It uses the Docker image `radstudio/paserver:latest`. The service configuration includes mapping a port from the host to the container, setting an environment variable for the server password, and mounting a volume from the host to the container. These settings are customizable through environment variables defined in a `.env` file located in the same directory as your `docker-compose.yml`.
+
```
-./pull-run.sh
+# .env file
+PA_SERVER_PASSWORD=securepass
+HOST_PORT=65000
+HOST_PATH=/path/on/host
```
-To pull and run the Docker Hub version of PAServer Docker for a non-debug/production environment use the `pull-run-production.sh` script
+To start your application, execute the following command in the directory containing your `docker-compose.yml`:
+
+```bash
+docker-compose up
```
-./pull-run-production.sh securepass123
+
+This command initiates the Docker Compose process, which reads the `docker-compose.yml` file and the `.env` file, applying the configurations to start your service as defined.
+
+This will pull the necessary image (if it's not already locally available), create the defined volumes, set the environment variables, and start your application on the specified ports.
+
+#### 📝 Note
+
+Ensure you replace `/path/on/host` with the actual path you wish to use for volume binding. The `latest` tag can be replaced with any specific version of the PAServer you wish to deploy.
+
+## 🛠️ Customizing Your Docker Image
+
+This guide will help you customize the PAServer image to suit your specific needs, such as adding additional files or folders, installing extra packages, and making other modifications.
+
+### 📁 Adding Files or Folders
+
+To add files or folders to your Docker image, use the `COPY` or `ADD` instruction in your Dockerfile. `COPY` is preferred for copying local files, while `ADD` can handle remote URLs and tar extraction.
+
+#### Example: Adding a Configuration File
+
+```dockerfile
+COPY ./myconfig.conf /etc/myapp/myconfig.conf
```
-To run the Docker Hub version of PAServer Docker for a debug/non-production environment use the `run.sh` script
+This command copies `myconfig.conf` from your project directory to `/etc/myapp/myconfig.conf` inside the Docker image.
+
+### 📦 Installing Extra Packages
+
+To install additional packages, you can modify the `RUN` command that installs packages. It's best to combine package installation commands into a single `RUN` instruction to reduce the number of layers in your Docker image.
+
+#### Example: Installing Git and Cmake
+
+```dockerfile
+RUN apt-get update && apt-get install -y \
+ git \
+ cmake \
+ && rm -rf /var/lib/apt/lists/*
+```
+
+Based on each project, specific libraries may be necessary. This command updates the package lists, installs _Git_ and _Cmake_, and cleans up afterward to keep the image size down.
+
+To avoid extra layering in the final Docker image, it's good practice to modify the existing `RUN apt-get update` command to include your required libraries.
+
+### 🛠️ Customizing Installation Commands
+
+You can customize the Dockerfile to change environment variables, download different versions of software, or modify the installation process.
+
+#### Example: Setting a Custom Environment Variable
+
+```dockerfile
+ENV MY_CUSTOM_VAR=myvalue
```
-./run.sh
+
+This sets an environment variable `MY_CUSTOM_VAR` that can be used by your application.
+
+### 🏗️ Building Your Custom Image
+
+After customizing your Dockerfile, you can build your Docker image using the `docker build` command.
+
+```bash
+docker build -t my-custom-paserver:latest .
```
-To run the Docker Hub version of paserver docker for a non-debug/production environment use the `run-production.sh` script
+This command builds a Docker image named `my-custom-paserver` with the `latest` tag, using the Dockerfile in the current directory.
+
+### 🔑 Using Build Arguments
+
+For values that might change between builds (like passwords or version numbers), you can use `ARG` instructions in your Dockerfile and pass values with the `--build-arg` option during the build.
+
+#### Example: Specifying a Custom Password
+
+```dockerfile
+ARG password=securepass
```
-./run-production.sh securepass123
+
+Build with a custom password:
+
+```bash
+docker build --build-arg password=mypassword -t my-custom-paserver:latest .
```
----
+### 💡 Tips
+
+- This repository provides a [`build.sh`] script that can be used as a template for simplifying custom builds.
+- Currently, this image is only compatible with `linux/amd64`. To avoid potential problems in arm setups, build the image with the arg `--platform linux/amd64`
+
+### 🛡️ Best Practices
+
+- **Minimize Layers**: Combine related commands into single `RUN` instructions where possible.
+- **Clean Up**: Remove unnecessary files and packages to keep the image size down.
+- **Use `.dockerignore`**: Add a `.dockerignore` file to your project to avoid copying unnecessary files into your Docker image.
+- **Secure Secrets**: Avoid hardcoding sensitive information in your Dockerfile. Use build arguments for build-time secrets and environment variables or Docker secrets for runtime secrets.
+
+## License and Copyright
+
+This software is Copyright © 2024 by [Embarcadero Technologies, Inc.][embarcadero]
-This software is Copyright © 2023 by [Embarcadero Technologies, Inc.](https://www.embarcadero.com/)
+_You may only use this software if you are an authorized licensee of an Embarcadero developer tools product. See the latest [software license agreement][embarcadero-license] for any updates._
-_You may only use this software if you are an authorized licensee of an Embarcadero developer tools product. See the latest [software license agreement](https://www.embarcadero.com/products/rad-studio/rad-studio-eula) for any updates._
+![Embarcadero(Black)](https://raw.githubusercontent.com/azapater/paserver-docker/main/.github/images/embt-logo-black.png#gh-light-mode-only)
+![Embarcadero(White)](https://raw.githubusercontent.com/azapater/paserver-docker/main/.github/images/embt-logo-white.png#gh-dark-mode-only)
-![Embarcadero(Black-100px)](https://user-images.githubusercontent.com/821930/211648635-c0db6930-120c-4456-a7ea-dc7612f01451.png#gh-light-mode-only)
-![Embarcadero(White-100px)](https://user-images.githubusercontent.com/821930/211649057-7f1f1f07-a79f-44d4-8fc1-87c819386ec6.png#gh-dark-mode-only)
+[dockerhub-paserver]: https://hub.docker.com/r/radstudio/paserver
+[radstudio]: https://www.embarcadero.com/products/rad-studio
+[paserver-docs]: http://docwiki.embarcadero.com/RADStudio/en/PAServer,_the_Platform_Assistant_Server_Application
+[github-interbase-docker]: https://github.com/Embarcadero/InterBase-Docker
+[github-radserver-docker]: https://github.com/Embarcadero/pa-radserver-docker
+[github-radserver-interbase-docker]: https://github.com/Embarcadero/pa-radserver-ib-docker
+[embarcadero]: https://www.embarcadero.com/
+[embarcadero-license]: https://www.embarcadero.com/products/rad-studio/rad-studio-eula
diff --git a/build.sh b/build.sh
old mode 100644
new mode 100755
index 0750f29..d488c81
--- a/build.sh
+++ b/build.sh
@@ -1,8 +1,24 @@
-#!/bin/bash
+#!/usr/bin/env bash
+# Exit script on error
+set -e
+
+# Variables for image name and tags
+IMAGE_NAME="radstudio/paserver"
+TAG_LATEST="latest"
+TAG_VERSION="athens"
+TAG_NUMERIC="12.1.1"
+
+# Build the Docker image with the first tag
docker build . \
--build-arg password=securepass \
--platform linux/amd64 \
- --tag=radstudio/paserver:latest \
- --tag=radstudio/paserver:athens \
- --tag=radstudio/paserver:12.1.1 \
+ --pull \
+ -t ${IMAGE_NAME}:${TAG_LATEST} \
+
+# Tag the built image with additional version tags
+docker tag "${IMAGE_NAME}:${TAG_LATEST}" "${IMAGE_NAME}:${TAG_VERSION}"
+docker tag "${IMAGE_NAME}:${TAG_LATEST}" "${IMAGE_NAME}:${TAG_NUMERIC}"
+
+# Echo a success message
+echo "Docker image ${IMAGE_NAME} tagged with ${TAG_LATEST}, ${TAG_VERSION}, and ${TAG_NUMERIC}"
\ No newline at end of file
diff --git a/paserver_docker.sh b/paserver_docker.sh
index 376c15c..c164e4f 100644
--- a/paserver_docker.sh
+++ b/paserver_docker.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
./paserver -password=$PA_SERVER_PASSWORD
status=$?
diff --git a/pull-run-production.sh b/pull-run-production.sh
deleted file mode 100644
index 1c355aa..0000000
--- a/pull-run-production.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/bash
-
-if [ "$1" = '' ]; then
- echo "RAD Server Docker paserver Pull-Run Script";
- echo "Required arguments: PAServer password";
- echo "ex: pull-run-production.sh securepass";
-else
- docker pull radstudio/paserver:latest
-
- bash ./run-production.sh $1
-fi
diff --git a/pull-run.sh b/pull-run.sh
deleted file mode 100644
index 173c455..0000000
--- a/pull-run.sh
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/bash
-
-docker pull radstudio/paserver:latest
-
-bash ./run.sh
diff --git a/run-production.sh b/run-production.sh
deleted file mode 100644
index 378e351..0000000
--- a/run-production.sh
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/bash
-
-if [ "$1" = '' ]; then
- echo "RAD Server Docker paserver Run Script";
- echo "Required arguments: PAServer password";
- echo "ex: run-production.sh securepass";
-else
- docker run --platform linux/amd64 -d -t -e PA_SERVER_PASSWORD=$1 -p 64211:64211 radstudio/paserver:latest
-fi
diff --git a/run.sh b/run.sh
old mode 100644
new mode 100755
index 3b3329d..ef226e9
--- a/run.sh
+++ b/run.sh
@@ -1,4 +1,91 @@
-#!/bin/bash
+#!/usr/bin/env bash
-echo "PAServer Password: securepass"
-docker run --cap-add=SYS_PTRACE --security-opt seccomp=unconfined --platform linux/amd64 -it -e PA_SERVER_PASSWORD=securepass -p 64211:64211 radstudio/paserver:latest
+NAME="paserver"
+BIND_PATH=""
+VERSION="latest"
+PRODUCTION=false
+PORT="64211"
+DETACH=false
+PASSWORD="securepass"
+
+while [ $# -gt 0 ]; do
+ case "$1" in
+ --name|-n)
+ if [[ "$1" != *=* ]]; then shift; fi # Value is next arg if no `=`
+ NAME="${1#*=}"
+ ;;
+ --path|-pa)
+ if [[ "$1" != *=* ]]; then shift; fi
+ BIND_PATH="${1#*=}"
+ ;;
+ --detach|-d)
+ # if [[ "$1" != *=* ]]; then shift; fi
+ DETACH=true
+ ;;
+ --port|-p)
+ if [[ "$1" != *=* ]]; then shift; fi
+ PORT="${1#*=}"
+ ;;
+ --production|-pr)
+ # if [[ "$1" != *=* ]]; then shift; fi
+ PRODUCTION=true
+ ;;
+ --version|-v)
+ if [[ "$1" != *=* ]]; then shift; fi
+ VERSION="${1#*=}"
+ ;;
+ --password|-pw)
+ if [[ "$1" != *=* ]]; then shift; fi
+ PASSWORD="${1#*=}"
+ ;;
+ --help|-h)
+ printf "Usage: run.sh [OPTIONS]\n\n"
+ printf "Example 1: run.sh --path /home/user/ --detach --port 64211 --production --password securepass --name my-paserver --version latest\n\n"
+ printf "Example 2: run.sh -pa /home/user/ -d -p 64211 -pr -pw securepass -n my-paserver -v latest\n\n"
+ printf "Options:\n"
+ printf " --name, -n NAME\tSpecify the name of the container - default: ${NAME}\n"
+ printf " --detach, -d\t\tRun in detached mode - default: ${DETACH}\n"
+ printf " --path, -pa\t\tBinds the container to a local folder - default: no bind\n"
+ printf " --port, -p PORT\tSpecify the port to use be used by PAServer - default: ${PORT}\n"
+ printf " --production, -pr\tEnable production mode - default: ${PRODUCTION}\n"
+ printf " --version, -v VERSION\tSpecify the PAServer tag to be used as image - default: ${VERSION}\n"
+ printf " --password, -pw PWD\tSet the password - default: ${PASSWORD}\n"
+ printf " --help, -h\t\tDisplay this help and exit\n"
+ exit 0
+ ;;
+ *)
+ >&2 printf "Error: Invalid argument\n"
+ exit 1
+ ;;
+ esac
+ shift
+done
+
+if [ "$BIND_PATH" != "" ]; then
+ BIND_PATH_ARG="--mount type=bind,source=$BIND_PATH,target=/root/PAServer/scratch-dir"
+fi
+
+if [ "$DETACH" = true ]; then
+ DETACH_ARG="-d -t"
+else
+ DETACH_ARG="-it"
+fi
+
+if [ "$PRODUCTION" = false ]; then
+ printf "Password: $PASSWORD\n"
+ printf "Port: $PORT\n"
+ printf "Detach: $DETACH\n"
+ printf "Production: $PRODUCTION\n"
+ printf "Path: $BIND_PATH\n"
+ printf "Name: $NAME\n"
+ printf "Version: $VERSION\n"
+
+ DEBUG_ARG="--cap-add=SYS_PTRACE --security-opt seccomp=unconfined"
+fi
+
+docker run $DEBUG_ARG \
+ $DETACH_ARG \
+ -e PA_SERVER_PASSWORD=$PASSWORD \
+ $BIND_PATH_ARG \
+ --name $NAME \
+ -p $PORT:64211 radstudio/paserver:$VERSION
\ No newline at end of file