espocrm / espocrm-docker

Official Docker Image for EspoCRM
https://hub.docker.com/r/espocrm/espocrm
GNU Affero General Public License v3.0
56 stars 34 forks source link

Add support for using Docker Compose Secrets instead of older `.env` pattern #50

Open andrewvaughan opened 2 weeks ago

andrewvaughan commented 2 weeks ago

Per the Docker's Docker Compose Secrets documentation, most Docker containers are starting to support the recommended _FILE suffix for sensitive information, allowing Docker Compose to use the more-secure secrets top-level element.

For example from the MySQL Docker image documentation:

Docker Secrets

As an alternative to passing sensitive information via environment variables, _FILE may be appended to the previously listed environment variables, causing the initialization script to load the values for those variables from files present in the container. In particular, this can be used to load passwords from Docker secrets stored in /run/secrets/<secret_name> files. For example:

$ docker run --name some-mysql -e MYSQL_ROOT_PASSWORD_FILE=/run/secrets/mysql-root -d mysql:tag

Currently, this is only supported for MYSQL_ROOT_PASSWORD, MYSQL_ROOT_HOST, MYSQL_DATABASE, MYSQL_USER, and MYSQL_PASSWORD.

By simply adding additional _FILE environment parameters, this change is entirely backwards compatible and will not disrupt any users that make use of the older .env pattern.

Motivation

This pattern is significantly more secure, as .env files have singular user access control. This also removes sensitive information from existing in the container's environment variables, which is a significant security improvement.

Especially for EspoCRM, there may be a realistic case where a development operations manager may want to give users the ability to manage their ESPOCRM_ADMIN_*** credentials, but not have access to the MySQL database credentials. With the existing .env pattern, that access is "all or nothing."

Following Docker's official recommendation in the link above, I recommend making seven (7) additional ***_FILE environment variables in the Dockerfile to match each of the following, existing variables:

Example Docker Compose File

As an example of what the improved Docker Compose file may look like for your documentation:

name: espocrm

# Note, the `version` top-level element is deprecated. See:
# https://docs.docker.com/compose/compose-file/04-version-and-name/

services:

  mysql:
    image: mysql:8
    container_name: mysql
    secrets:
      - mysql_root_password
      - mysql_database
      - mysql_user
      - mysql_password
    environment:
      MYSQL_ROOT_PASSWORD_FILE: "/run/secrets/mysql_root_password"
      MYSQL_DATABASE_FILE: "/run/secrets/mysql_database"
      MYSQL_USER_FILE: "/run/secrets/mysql_user"
      MYSQL_PASSWORD_FILE: "/run/secrets/mysql_password"
    volumes:
      - mysql:/var/lib/mysql
    restart: always

  espocrm:
    image: espocrm/espocrm
    container_name: espocrm
    secrets:
      - mysql_host
      - mysql_port
      - mysql_database
      - mysql_user
      - mysql_password
      - espocrm_admin_user
      - espocrm_admin_password
    environment:
      ESPOCRM_DATABASE_PLATFORM: Mysql
      ESPOCRM_DATABASE_HOST_FILE: "/run/secrets/mysql_host"
      ESPOCRM_DATABASE_PORT_FILE: "/run/secrets/mysql_port"
      ESPOCRM_DATABASE_NAME_FILE: "/run/secrets/mysql_database"
      ESPOCRM_DATABASE_USER_FILE: "/run/secrets/mysql_user"
      ESPOCRM_DATABASE_PASSWORD_FILE: "/run/secrets/mysql_password"
      ESPOCRM_ADMIN_USERNAME_FILE: "/run/secrets/espocrm_admin_user"
      ESPOCRM_ADMIN_PASSWORD_FILE: "/run/secrets/espocrm_admin_password"
      ESPOCRM_SITE_URL: "http://localhost:8080"
    volumes:
      - espocrm:/var/www/html
    restart: always
    ports:
      - 8080:80

  espocrm-daemon:
    image: espocrm/espocrm
    container_name: espocrm-daemon
    volumes:
      - espocrm:/var/www/html
    restart: always
    entrypoint: docker-daemon.sh

  espocrm-websocket:
    image: espocrm/espocrm
    container_name: espocrm-websocket
    environment:
      ESPOCRM_CONFIG_USE_WEB_SOCKET: "true"
      ESPOCRM_CONFIG_WEB_SOCKET_URL: "ws://localhost:8081"
      ESPOCRM_CONFIG_WEB_SOCKET_ZERO_M_Q_SUBSCRIBER_DSN: "tcp://*:7777"
      ESPOCRM_CONFIG_WEB_SOCKET_ZERO_M_Q_SUBMISSION_DSN: "tcp://espocrm-websocket:7777"
    volumes:
      - espocrm:/var/www/html
    restart: always
    entrypoint: docker-websocket.sh
    ports:
      - 8081:8080

volumes:
  mysql:
  espocrm:

# The `secrets` directory should have `770` permissions and be owned by the
# user/group running the Docker daemon (usually `root`).
secrets:
  mysql_host:
    file: "./secrets/mysql/host"
  mysql_port:
    file: "./secrets/mysql/port"
  mysql_database:
    file: "./secrets/mysql/database_name"
  mysql_root_password:
    file: "./secrets/mysql/root_password"
  mysql_database:
    file: "./secrets/mysql/database"
  mysql_user:
    file: "./secrets/mysql/user"
  mysql_password:
    file: "./secrets/mysql/password"
  espocrm_admin_user:
    file: "./secrets/espocrm/admin_username"
  espocrm_admin_password:
    file: "./secrets/espocrm/admin_password"

As an example for implementation of this change, here is how MySQL manages this:

https://github.com/docker-library/mysql/blob/1a703318803fa85bf69cb5d2e5b3f1c4087627b5/docker-entrypoint.sh#L24-L43

And WordPress, as a more dynamic alternative:

https://github.com/docker-library/wordpress/blob/8c2ded17022e67c6accacfae637c5a577ce169af/wp-config-docker.php#L26-L40

tmachyshyn commented 1 week ago

Thanks for your feature request. We will review it.