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 -Embarcadero RAD Studio -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) +Embarcadero RAD Studio + +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