Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added #9313: Add new fpm-alpine docker image and docker secrets support #9331

Merged
merged 7 commits into from
Apr 21, 2021
Merged

Added #9313: Add new fpm-alpine docker image and docker secrets support #9331

merged 7 commits into from
Apr 21, 2021

Conversation

Mateus-Romera
Copy link
Contributor

@Mateus-Romera Mateus-Romera commented Mar 23, 2021

Description

Add php-fpm-alpine image and docker secrets support.
I know I probably should have created two separate PRs, but I was only able to test the docker's secret support with this new docker image due to lack of time.

PHP-FPM-ALPINE

I tried to create a production-ready php-fpm-alpine image following the best practices of wordpress and php-fpm official docker images. (does not make it perfect. Feel free to point anything wrong!)
I added easy-to-use support for development, but it’s worth saying that I haven’t tested this image extensively for this purpose.
This image contains 226MB uncompressed.

DOCKER-SECRETS

Add docker secrets support using simple shell script helper function that is capable of converting environment variables containing the suffix '_FILE' into their stripped counterparts.
This function was cribbed from the official docker netxtcloud repository:
https://github.com/nextcloud/docker/blob/9b057aafb0c41bab63870277c53307d3d6dc572b/docker-entrypoint.sh

I also created a new .env file and docker-entrypoint.sh with the necessary modifications so as not to break the current docker workflow using other snipeit images.

Initial variable support for docker secrets:

Variable Secret variable
APP_KEY APP_KEY_FILE
DB_HOST DB_HOST_FILE
DB_PORT DB_PORT_FILE
DB_DATABASE DB_DATABASE_FILE
DB_USERNAME DB_USERNAME_FILE
DB_PASSWORD DB_PASSWORD_FILE
REDIS_HOST REDIS_HOST_FILE
REDIS_PASSWORD REDIS_PASSWORD_FILE
REDIS_PORT REDIS_PORT_FILE
MAIL_HOST MAIL_HOST_FILE
MAIL_PORT MAIL_PORT_FILE
MAIL_USERNAME MAIL_USERNAME_FILE
MAIL_PASSWORD MAIL_PASSWORD_FILE

If desired, you can add more support for variables by adding including them directly to the shell script.

With this we could deploy snipeIT more securely.

Closes # (#9313)

Type of change

  • New feature (non-breaking change which adds functionality)
  • This change requires a documentation update

How Has This Been Tested?

The fpm-alpine image was built using the new docker BuildKit module.

docker buildx build \
  --file Dockerfile.fpm-alpine \
  --tag snipe/snipe-it:5.1.3-fpm-alpine .

Test was done using docker-compose and fpm-alpine image above as base to build my nginx + snipeit-fpm-alpine image:

docker-compose.yml:

version: "3.9"

secrets:
  snipeit-app-key:
    file: ./docker/snipeit-fpm_nginx/secrets/fake-snipeit-app-key
  mysql-db-name:
    file: ./docker/mariadb/secrets/fake-mysql-db-name
  mysql-db-user-name:
    file: ./docker/mariadb/secrets/fake-mysql-db-user-name
  mysql-db-user-pw:
    file: ./docker/mariadb/secrets/fake-mysql-db-user-pw

volumes:
  config:
  database:

services:
  snipeit:
    build:
      context: .
      dockerfile: ./docker/snipeit-fpm_nginx/snipeit-fpm_nginx.dockerfile
    image: snipeit-fpm_nginx
    secrets:
      - snipeit-app-key
      - mysql-db-name
      - mysql-db-user-name
      - mysql-db-user-pw
    env_file: .env
    environment:
      # SnipeIT settings
      APP_ENV: production
      APP_DEBUG: "false"
      APP_TIMEZONE: 'America/Sao_Paulo'
      APP_LOCALE: en
      APP_URL: localhost:8080
      APP_KEY_FILE: /run/secrets/snipeit-app-key
      # Database settings
      DB_HOST: mariadb
      DB_PORT: 3306
      DB_DATABASE_FILE: /run/secrets/mysql-db-name
      DB_USERNAME_FILE: /run/secrets/mysql-db-user-name
      DB_PASSWORD_FILE: /run/secrets/mysql-db-user-pw
      # Mail settings
      # MAIL_HOST: 
      # MAIL_PORT: 587
      # MAIL_USERNAME: 
      # MAIL_PASSWORD: 
      # Nginx settings
      NGINX_HOST: localhost
      NGINX_PORT: 8080
      NGINX_UPSTREAM_CONNECTION_TYPE: 'sock'
      NGINX_UPSTREAM: unix:/var/run/php-fpm.sock
      NGINX_UPSTREAM_PORT: ''
    ports:
      - "8080:8080"
    volumes:
      - config:/var/lib/snipeit
      # h5bp configs overwrite
      - "./docker/snipeit-fpm_nginx/nginx/h5bp-overwrite/nginx.conf:/etc/nginx/nginx.conf:ro"
      # Nginx default no-ssl config template
      - "./docker/snipeit-fpm_nginx/nginx/templates/no-ssl.conf.template:/etc/nginx/templates/default.conf.template:ro"
    security_opt:
      - no-new-privileges
    depends_on:
      - mariadb
    container_name: snipeit_snipeit-fpm_nginx
    restart: unless-stopped

  mariadb:
    build:
      context: .
      dockerfile: ./docker/mariadb/mariadb.dockerfile
    image: snipeit_mariadb
    secrets:
      - mysql-root-pw
      - mysql-db-name
      - mysql-db-user-name
      - mysql-db-user-pw
    environment:
      MYSQL_ROOT_PASSWORD_FILE: /run/secrets/mysql-root-pw
      MYSQL_DATABASE_FILE: /run/secrets/mysql-db-name
      MYSQL_USER_FILE: /run/secrets/mysql-db-user-name
      MYSQL_PASSWORD_FILE: /run/secrets/mysql-db-user-pw
    volumes:
      - database:/var/lib/mysql
    security_opt:
      - no-new-privileges
    container_name: snipeit_mariadb
    restart: unless-stopped

Test Configuration:

  • MariaDB version: mariadb:10.5.9-focal
  • Webserver version: nginx:1.19.8-alpine
  • OS version: Pop!_OS

Checklist:

- APP_KEY_FILE        -> APP_KEY;

- DB_HOST_FILE        -> DB_HOST;
- DB_PORT_FILE        -> DB_PORT;
- DB_DATABASE_FILE    -> DB_DATABASE;
- DB_USERNAME_FILE    -> DB_USERNAME;
- DB_PASSWORD_FILE    -> DB_PASSWORD;

- REDIS_HOST_FILE     -> REDIS_HOST;
- REDIS_PASSWORD_FILE -> REDIS_PASSWORD;
- REDIS_PORT_FILE     -> REDIS_PORT;

- MAIL_HOST_FILE      -> MAIL_HOST;
- MAIL_PORT_FILE      -> MAIL_PORT;
- MAIL_USERNAME_FILE  -> MAIL_USERNAME;
- MAIL_PASSWORD_FILE  -> MAIL_PASSWORD;
@welcome
Copy link

welcome bot commented Mar 23, 2021

💖 Thanks for this pull request! 💖

We use semantic commit messages to streamline the release process and easily generate changelogs between versions. Before your pull request can be merged, you should update your pull request title to start with a semantic prefix if it doesn't have one already.

Examples of commit messages with semantic prefixes:

  • Fixed #<issue number>: don't overwrite prevent_default if default wasn't prevented
  • Added #<issue number>: add checkout functionality to assets
  • Improved Asset Checkout: use new notification method for checkout

Things that will help get your PR across the finish line:

  • Document any user-facing changes you've made.
  • Include tests when adding/changing behavior.
  • Include screenshots and animated GIFs whenever possible.

We get a lot of pull requests on this repo, so please be patient and we will get back to you as soon as we can.

@Mateus-Romera Mateus-Romera changed the title Add new fpm-alpine docker image and docker secrets support Added #9313: Add new fpm-alpine docker image and docker secrets support Mar 23, 2021
@snipe
Copy link
Owner

snipe commented Mar 23, 2021

I'm a little worried about keeping the docker config files and the regular config files in sync though. @uberbrady - can you think of an easier way to maybe handle this?

@Mateus-Romera
Copy link
Contributor Author

You are right. Wordpress official docker image does the same thing, but only with one file, wp-config.php. If we added support for docker secrets to every variable, we would have to create a lot of copies, this is not ideal at all.

Perhaps if we replace getenv() function with getenv_docker() for each regular config files, since the getenv_docker() function will try to search for a '_FILE' variable, but if not found, it will fallback to find the normal variable (without '_FILE') using getenv() function. But this would integrate docker directly into the code, which may also not be ideal.

What do you think?

@Mateus-Romera
Copy link
Contributor Author

Mateus-Romera commented Mar 31, 2021

@snipe Hello again,

I have made some changes.
Instead of copying php config files and adding docker secrets support from there, I created a shell function that cares of that in the docker-entrypoint. Actualy, I just used the same function used in the nextcloud official docker image: https://github.com/nextcloud/docker/blob/9b057aafb0c41bab63870277c53307d3d6dc572b/docker-entrypoint.sh

This way we can forget about keeping the docker config files and the regular config files in sync.
I think this should be much better than the first implementation.
What do you think?

If this is acceptable, then I will also edit the PR description.

GitHub
⛴ Docker image of Nextcloud. Contribute to nextcloud/docker development by creating an account on GitHub.

@snipe
Copy link
Owner

snipe commented Apr 6, 2021

@uberbrady and @jerm - can you both take a gander at this and see it all looks okay to you both?

@snipe snipe requested a review from jerm April 6, 2021 02:44
@snipe snipe added the docker label Apr 6, 2021
@snipe snipe merged commit fdcb63f into snipe:develop Apr 21, 2021
@welcome
Copy link

welcome bot commented Apr 21, 2021

Congrats on merging your first pull request! 🎉🎉🎉

@major-mayer
Copy link

Nice to see that there is finally a officially supported Dockerfile that is using PHP-FPM.
Is this image already (automatically) built somewhere?
I've looked through Docker Hub but did not find any Alpine or FPM images, just the regular Snipe-It image.

If not, do we have some guide how to manually build the image?
I've tried downloading the repository and building the image, but got an error about missing BuildKit or so

@Mateus-Romera
Copy link
Contributor Author

Hello!
That's cool that you liked it!
I wanted to automate the image build with every new release but I just lacked the time to do so.
I will probably do this later but in the meantime, what was the error you were getting with buildkit? Maybe I could help you in this regard

@Mateus-Romera
Copy link
Contributor Author

Mateus-Romera commented Oct 31, 2021

@major-mayer hello again,

I created a new repository with the php-fpm alpine docker image using the latest Snipe-IT release, you are welcome to take a look: https://hub.docker.com/r/pirasbro/snipe-it

I want to create something similar to docker official images, build, tagging and publish docker images using the bashbew tool, but in the meantime, I'm doing this manually since it's my first attempt to do something like this.

If you encounter any problem, don't hesitate to contact me.
Good luck!

@major-mayer
Copy link

major-mayer commented Nov 1, 2021

Hi @Mateus-Romera ,
Great work with that repository. That's exactly what i wished :)
I just tried to deploy the container using this Docker-Compose file:

version: '3'

volumes:
  web_data:
  snipe_data: # only for debugging

services:
  snipeit:
    container_name: snipeit-fpm
    image: pirasbro/snipe-it:5.3.0-fpm-alpine
    environment:
      # SnipeIT settings
      APP_URL: localhost:9001
      APP_KEY: base64:CdNywz90QeGfAvL4nw7sqHwr9nI8v4z+yYcWpEgH+4g=
      # Database settings
      DB_HOST: mariadb
      DB_PORT: 3306
      DB_DATABASE: snipeit
      DB_USERNAME: snipeit
      DB_PASSWORD: -------
      # Session settings
      SECURE_COOKIES: "false"
    volumes:
      - web_data:/var/www/html
      - snipe_data:var/lib/snipeit  # only for debugging
    external_links:
      - mariadb 

( The reverse proxy and database are defined externally)
Unfortunately when the container starts it always reports this error:

/usr/local/bin/docker-snipeit-entrypoint: line 141: /var/lib/snipeit/data: Permission denied

That's why i created the second volume, i thought it could maybe help, but it didn't.
For testing i created a bind mount for /var/lib/snipeit and checked if folders were created and yes indeed:

/media/NasServer/snipeit-test >>> tree -h                                      
.
├── [   0]  data
│   ├── [   0]  private_uploads
│   └── [   0]  uploads
│       ├── [   0]  accessories
│       ├── [   0]  avatars
│       ├── [   0]  barcodes
│       ├── [   0]  categories
│       ├── [   0]  companies
│       ├── [   0]  components
│       ├── [   0]  consumables
│       ├── [   0]  departments
│       ├── [   0]  locations
│       ├── [   0]  manufacturers
│       ├── [   0]  models
│       └── [   0]  suppliers
├── [   0]  dumps
└── [   0]  keys

17 directories, 0 files

So it seems that the installer can create some folders but has some permission errors in the entry script.
Any ideas what could be wrong?

Edit:
Seems that the error comes from here:

chown -R www-data:www-data \
    /var/www/html/storage/logs/laravel.log
    /var/lib/snipeit/data \
    /var/lib/snipeit/dumps \
    /var/lib/snipeit/keys

I still wonder why it's unable to do a chown for directories that are completely under the control of the container.

@Mateus-Romera
Copy link
Contributor Author

Hello again @major-mayer ,

I made a lot of mistakes on this image but they should be solved by now.
Could you please run docker pull again and see if it works for you?
I double checked everything and it was working correctly.

If you encounter any more issues, please create them inside my repository instead of using this PR for a better tracking on my part.

Thanks and good luck!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants