diff --git a/.env b/.env
index 1e94eadad2725..1010665213d56 100644
--- a/.env
+++ b/.env
@@ -1,11 +1,23 @@
-DOCKER_CLIENT_TIMEOUT=120
-COMPOSE_HTTP_TIMEOUT=120
+# docker config
+DOCKER_CLIENT_TIMEOUT=320
+COMPOSE_HTTP_TIMEOUT=320
COMPOSE_PROJECT_NAME=po
COMPOSE_PATH_SEPARATOR=;
COMPOSE_FILE=docker-compose.yml;docker/dev.yml
+# exposition of product opener, leave blank to expose on all ports
+# ends with ":"
+PRODUCT_OPENER_EXPOSE=127.0.0.1:
+# same but for all admin tools
+ADMIN_EXPOSE=127.0.0.1:
+
+# version for backend and frontend images
TAG=latest
-WWW_DATA_HOST_USER=${UID}
+# setting to align host user to internal user
+USER_UID=1000
+USER_GID=1000
+
+# env vars
PRODUCERS_PLATFORM=0
PRODUCT_OPENER_DOMAIN=openfoodfacts.localhost
PRODUCT_OPENER_PORT=80
@@ -17,7 +29,7 @@ MONGODB_HOST=mongodb
MONGODB_CACHE_SIZE=8 # GB
MONGO_INITDB_ROOT_USERNAME=root
MONGO_INITDB_ROOT_PASSWORD=test
-ROBOTOFF_URL=robotoff.openfoodfacts.localhost
+ROBOTOFF_URL=http://host.docker.internal:5500 # connect to Robotoff running in separate docker-compose deployment
GOOGLE_CLOUD_VISION_API_KEY=
CROWDIN_PROJECT_IDENTIFIER=
CROWDIN_PROJECT_KEY=
@@ -25,3 +37,5 @@ GEOLITE2_PATH=
GEOLITE2_LICENSE_KEY=
GEOLITE2_ACCOUNT_ID=
ELASTICSEARCH_HOSTS=
+LOG_LEVEL_ROOT=TRACE
+LOG_LEVEL_MONGODB=TRACE
diff --git a/.github/workflows/container-deploy.yml b/.github/workflows/container-deploy.yml
index 1d09829bea226..e515348a494c5 100644
--- a/.github/workflows/container-deploy.yml
+++ b/.github/workflows/container-deploy.yml
@@ -94,6 +94,9 @@ jobs:
echo "COMPOSE_PATH_SEPARATOR=;" >> .env
echo "COMPOSE_FILE=docker-compose.yml;docker/prod.yml;docker/geolite2.yml;docker/monitor.yml" >> .env
+ echo "PRODUCT_OPENER_EXPOSE=" >> .env
+ echo "ADMIN_EXPOSE=" >> .env
+
# Set App variables
echo "TAG=sha-${{ github.sha }}" >> .env
echo "PRODUCERS_PLATFORM=0" >> .env
@@ -111,6 +114,8 @@ jobs:
echo "GEOLITE2_PATH=${{ secrets.GEOLITE2_PATH }}" >> .env
echo "GEOLITE2_LICENSE_KEY=${{ secrets.GEOLITE2_LICENSE_KEY }}" >> .env
echo "GEOLITE2_ACCOUNT_ID=${{ secrets.GEOLITE2_ACCOUNT_ID }}" >> .env
+ echo "LOG_LEVEL_ROOT=ERROR" >> .env
+ echo "LOG_LEVEL_MONGODB=ERROR" >> .env
# Override domain name in nginx.conf
sed -i.bak "s/productopener.localhost/${{ secrets.PRODUCT_OPENER_DOMAIN }}/g" ./conf/nginx.conf
@@ -129,6 +134,20 @@ jobs:
cd ${{ matrix.env }}
make create_external_volumes
+ - name: init backend
+ uses: appleboy/ssh-action@master
+ with:
+ host: ${{ secrets.HOST }}
+ username: ${{ secrets.USERNAME }}
+ key: ${{ secrets.SSH_PRIVATE_KEY }}
+ proxy_host: ${{ secrets.PROXY_HOST }}
+ proxy_username: ${{ secrets.USERNAME }}
+ proxy_key: ${{ secrets.SSH_PRIVATE_KEY }}
+ script_stop: false
+ script: |
+ cd ${{ matrix.env }}
+ make init_backend
+
- name: Start services
uses: appleboy/ssh-action@master
with:
@@ -142,8 +161,8 @@ jobs:
script: |
cd ${{ matrix.env }}
make hdown
+ make build_lang
make up
- make setup_incron
- name: Check services are up
uses: appleboy/ssh-action@master
@@ -175,7 +194,7 @@ jobs:
cd ${{ matrix.env }}
make prune
- - uses: frankie567/grafana-annotation-action@v1.0.2
+ - uses: frankie567/grafana-annotation-action@v1.0.3
if: ${{ always() }}
with:
apiHost: https://grafana.openfoodfacts.org
diff --git a/.github/workflows/crowdin-per-language.yml b/.github/workflows/crowdin-per-language.yml
index 756f9fc0ce48a..45809ddd7a52f 100644
--- a/.github/workflows/crowdin-per-language.yml
+++ b/.github/workflows/crowdin-per-language.yml
@@ -22,7 +22,7 @@ jobs:
- name: Checkout
uses: actions/checkout@v2
- name: Matrix
- uses: crowdin/github-action@1.4.0
+ uses: crowdin/github-action@1.4.1
with:
upload_translations: false # default is false
download_translations: true
diff --git a/.github/workflows/crowdin.yml b/.github/workflows/crowdin.yml
index 0b7a7af8c3d41..e38b5b91c5bc0 100644
--- a/.github/workflows/crowdin.yml
+++ b/.github/workflows/crowdin.yml
@@ -17,7 +17,7 @@ jobs:
- name: Checkout
uses: actions/checkout@v2
- name: crowdin action
- uses: crowdin/github-action@1.4.0
+ uses: crowdin/github-action@1.4.1
with:
upload_translations: false # default is false
# Use this option to upload translations for a single specified language
diff --git a/.gitignore b/.gitignore
index d3832957b9d01..58d27086180b1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,9 +14,10 @@ Thumbs.db
.vstags
# Logs
+logs/
+debug/
Store.debug.txt
*.log
-logs/modperl_error_log
nytprof*.out
# Local databases
@@ -36,6 +37,9 @@ html/js/dist
html/images/icons/dist
html/images/attributes/*.svg
+# Images
+html/images/products/*
+
# Don't store helm dependencies in our git repo
docker/productopener/charts
docker/logs
diff --git a/Dockerfile b/Dockerfile
index c23a0cb722e69..9b6ad815bb506 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,138 +1,152 @@
-FROM bitnami/minideb:buster AS modperl
+# syntax=docker/dockerfile:1.2
+# Base user uid / gid keep 1000 on prod, align with your user on dev
+ARG USER_UID=1000
+ARG USER_GID=1000
-# Install cpm to install cpanfile dependencies
-RUN set -x \
- && install_packages \
- apache2 \
- apt-utils \
- cpanminus \
- g++ \
- gcc \
- less \
- libapache2-mod-perl2 \
- # libexpat1-dev \
- make \
- wget \
- imagemagick \
- graphviz \
- tesseract-ocr \
- # perlmagick \
- #
- # Packages from ./cpanfile:
- # If cpanfile specifies a newer version than apt has, cpanm will install the newer version.
- #
- libtie-ixhash-perl \
- libwww-perl \
- libimage-magick-perl \
- libxml-encoding-perl \
- libtext-unaccent-perl \
- libmime-lite-perl \
- libcache-memcached-fast-perl \
- libjson-pp-perl \
- libclone-perl \
- libcrypt-passwdmd5-perl \
- libencode-detect-perl \
- libgraphics-color-perl \
- libbarcode-zbar-perl \
- libxml-feedpp-perl \
- liburi-find-perl \
- libxml-simple-perl \
- libexperimental-perl \
- libapache2-request-perl \
- libdigest-md5-perl \
- libtime-local-perl \
- libdbd-pg-perl \
- libtemplate-perl \
- liburi-escape-xs-perl \
- # NB: not available in ubuntu 1804 LTS:
- libmath-random-secure-perl \
- libfile-copy-recursive-perl \
- libemail-stuffer-perl \
- liblist-moreutils-perl \
- libexcel-writer-xlsx-perl \
- libpod-simple-perl \
- liblog-any-perl \
- liblog-log4perl-perl \
- liblog-any-adapter-log4perl-perl \
- # NB: not available in ubuntu 1804 LTS:
- libgeoip2-perl \
- libemail-valid-perl \
- #
- # cpan dependencies that can be satisfied by apt even if the package itself can't:
- #
- # Action::Retry
- libmath-fibonacci-perl \
- # Algorithm::CheckDigits
- libprobe-perl-perl \
- # CLDR::Number
- libmath-round-perl \
- libsoftware-license-perl \
- libtest-differences-perl \
- libtest-exception-perl \
- # Data::Dumper::AutoEncode
- # NB: not available in ubuntu 1804 LTS:
- libmodule-build-pluggable-perl \
- libclass-accessor-lite-perl \
- # DateTime
- libclass-singleton-perl \
- # DateTime::Locale
- libfile-sharedir-install-perl \
- # Encode::Punycode
- libnet-idn-encode-perl \
- libtest-nowarnings-perl \
- # File::chmod::Recursive
- libfile-chmod-perl \
- # GeoIP2
- libdata-dumper-concise-perl \
- libdata-printer-perl \
- libdata-validate-ip-perl \
- libio-compress-perl \
- libjson-maybexs-perl \
- liblist-allutils-perl \
- liblist-someutils-perl \
- # GraphViz2
- libdata-section-simple-perl \
- libfile-which-perl \
- libipc-run3-perl \
- liblog-handler-perl \
- libtest-deep-perl \
- libwant-perl \
- # Image::OCR::Tesseract
- libfile-find-rule-perl \
- liblinux-usermod-perl \
- # Locale::Maketext::Lexicon::Getcontext
- liblocale-maketext-lexicon-perl \
- # Log::Any::Adapter::TAP
- liblog-any-adapter-tap-perl \
- # Math::Random::Secure
- libcrypt-random-source-perl \
- libmath-random-isaac-perl \
- libtest-sharedfork-perl \
- libtest-warn-perl \
- # Mojo::Pg
- libsql-abstract-perl \
- # MongoDB
- libauthen-sasl-saslprep-perl \
- libauthen-scram-perl \
- libbson-perl \
- libclass-xsaccessor-perl \
- libconfig-autoconf-perl \
- libdigest-hmac-perl \
- libpath-tiny-perl \
- libsafe-isa-perl \
- # Spreadsheet::CSV
- libspreadsheet-parseexcel-perl \
- # Test::Number::Delta
- libtest-number-delta-perl \
- libdevel-size-perl \
- gnumeric \
- incron
-# Run www-data user as host user 'off'
-ARG WWW_DATA_HOST_USER=1000
-RUN usermod -u $WWW_DATA_HOST_USER www-data
+######################
+# Base modperl image stage
+######################
+FROM bitnami/minideb:buster AS modperl
+# Install cpm to install cpanfile dependencies
+RUN --mount=type=cache,id=apt-cache,target=/var/cache/apt set -x && \
+ install_packages \
+ apache2 \
+ apt-utils \
+ cpanminus \
+ g++ \
+ gcc \
+ less \
+ libapache2-mod-perl2 \
+ # libexpat1-dev \
+ make \
+ wget \
+ imagemagick \
+ graphviz \
+ tesseract-ocr \
+ # perlmagick \
+ #
+ # Packages from ./cpanfile:
+ # If cpanfile specifies a newer version than apt has, cpanm will install the newer version.
+ #
+ libtie-ixhash-perl \
+ libwww-perl \
+ libimage-magick-perl \
+ libxml-encoding-perl \
+ libtext-unaccent-perl \
+ libmime-lite-perl \
+ libcache-memcached-fast-perl \
+ libjson-pp-perl \
+ libclone-perl \
+ libcrypt-passwdmd5-perl \
+ libencode-detect-perl \
+ libgraphics-color-perl \
+ libbarcode-zbar-perl \
+ libxml-feedpp-perl \
+ liburi-find-perl \
+ libxml-simple-perl \
+ libexperimental-perl \
+ libapache2-request-perl \
+ libdigest-md5-perl \
+ libtime-local-perl \
+ libdbd-pg-perl \
+ libtemplate-perl \
+ liburi-escape-xs-perl \
+ # NB: not available in ubuntu 1804 LTS:
+ libmath-random-secure-perl \
+ libfile-copy-recursive-perl \
+ libemail-stuffer-perl \
+ liblist-moreutils-perl \
+ libexcel-writer-xlsx-perl \
+ libpod-simple-perl \
+ liblog-any-perl \
+ liblog-log4perl-perl \
+ liblog-any-adapter-log4perl-perl \
+ # NB: not available in ubuntu 1804 LTS:
+ libgeoip2-perl \
+ libemail-valid-perl \
+ #
+ # cpan dependencies that can be satisfied by apt even if the package itself can't:
+ #
+ # Action::Retry
+ libmath-fibonacci-perl \
+ # Algorithm::CheckDigits
+ libprobe-perl-perl \
+ # CLDR::Number
+ libmath-round-perl \
+ libsoftware-license-perl \
+ libtest-differences-perl \
+ libtest-exception-perl \
+ # Data::Dumper::AutoEncode
+ # NB: not available in ubuntu 1804 LTS:
+ libmodule-build-pluggable-perl \
+ libclass-accessor-lite-perl \
+ # DateTime
+ libclass-singleton-perl \
+ # DateTime::Locale
+ libfile-sharedir-install-perl \
+ # Encode::Punycode
+ libnet-idn-encode-perl \
+ libtest-nowarnings-perl \
+ # File::chmod::Recursive
+ libfile-chmod-perl \
+ # GeoIP2
+ libdata-dumper-concise-perl \
+ libdata-printer-perl \
+ libdata-validate-ip-perl \
+ libio-compress-perl \
+ libjson-maybexs-perl \
+ liblist-allutils-perl \
+ liblist-someutils-perl \
+ # GraphViz2
+ libdata-section-simple-perl \
+ libfile-which-perl \
+ libipc-run3-perl \
+ liblog-handler-perl \
+ libtest-deep-perl \
+ libwant-perl \
+ # Image::OCR::Tesseract
+ libfile-find-rule-perl \
+ liblinux-usermod-perl \
+ # Locale::Maketext::Lexicon::Getcontext
+ liblocale-maketext-lexicon-perl \
+ # Log::Any::Adapter::TAP
+ liblog-any-adapter-tap-perl \
+ # Math::Random::Secure
+ libcrypt-random-source-perl \
+ libmath-random-isaac-perl \
+ libtest-sharedfork-perl \
+ libtest-warn-perl \
+ # Mojo::Pg
+ libsql-abstract-perl \
+ # MongoDB
+ libauthen-sasl-saslprep-perl \
+ libauthen-scram-perl \
+ libbson-perl \
+ libclass-xsaccessor-perl \
+ libconfig-autoconf-perl \
+ libdigest-hmac-perl \
+ libpath-tiny-perl \
+ libsafe-isa-perl \
+ # Spreadsheet::CSV
+ libspreadsheet-parseexcel-perl \
+ # Test::Number::Delta
+ libtest-number-delta-perl \
+ libdevel-size-perl \
+ gnumeric \
+ incron
+
+# Run www-data user as host user 'off' or developper uid
+ARG USER_UID
+ARG USER_GID
+RUN usermod --uid $USER_UID www-data && \
+ groupmod --gid $USER_GID www-data
+
+
+######################
# Stage for installing/compiling cpanfile dependencies
+######################
FROM modperl AS builder
WORKDIR /tmp
@@ -141,14 +155,12 @@ WORKDIR /tmp
COPY ./cpanfile /tmp/cpanfile
# Add ProductOpener runtime dependencies from cpan
-RUN cpanm --notest --quiet --skip-satisfied --local-lib /tmp/local/ --installdeps .
-
-# Stage for installing/compiling cpanfile dependencies with dev dependencies
-FROM builder AS builder-vscode
+RUN --mount=type=cache,id=cpanm-cache,target=/root/.cpanm cpanm --notest --quiet --skip-satisfied --local-lib /tmp/local/ --installdeps .
-# Add ProductOpener runtime dependencies from cpan
-RUN cpanm --with-develop --notest --quiet --skip-satisfied --local-lib /tmp/local/ --installdeps .
+######################
+# backend production image stage
+######################
FROM modperl AS runnable
# Prepare Apache to include our custom config
@@ -158,44 +170,41 @@ RUN rm /etc/apache2/sites-enabled/000-default.conf
COPY --from=builder /tmp/local/ /opt/perl/local/
ENV PERL5LIB="/opt/product-opener/lib/:/opt/perl/local/lib/perl5/"
ENV PATH="/opt/perl/local/bin:${PATH}"
+# Create writable dirs and change ownership to www-data
+RUN \
+ mkdir -p var/run/apache2/ && \
+ chown www-data:www-data var/run/apache2/ && \
+ for path in data html_data users products product_images orgs new_images logs tmp; do \
+ mkdir -p /mnt/podata/${path}; \
+ done && \
+ chown www-data:www-data -R /mnt/podata && \
+ # Create symlinks of data files that are indeed conf data in /mnt/podata (because we currently mix data and conf data)
+ for path in ecoscore emb_codes forest-footprint ingredients lang packager-codes po taxonomies templates; do \
+ ln -sf /opt/product-opener/${path} /mnt/podata/${path}; \
+ done && \
+ # Create some necessary files to ensure permissions in volumes
+ mkdir -p /opt/product-opener/html/data/ && \
+ mkdir -p /opt/product-opener/html/images/ && \
+ chown www-data:www-data -R /opt/product-opener/html/ && \
+ # logs dir
+ mkdir -p /var/log/apache2/ && \
+ chown www-data:www-data -R /var/log
+# Install Product Opener from the workdir
+COPY --chown=www-data:www-data . /opt/product-opener/
+RUN \
+ # www-data user shall be able to use incron
+ echo www-data >> /etc/incron.allow && \
+ incrontab -u www-data /opt/product-opener/conf/incron.conf
EXPOSE 80
COPY ./docker/docker-entrypoint.sh /
+WORKDIR /opt/product-opener/
+USER www-data
ENTRYPOINT [ "/docker-entrypoint.sh" ]
+# default command is apache2ctl start
CMD ["apache2ctl", "-D", "FOREGROUND"]
-FROM runnable AS runnable-vscode
-COPY --from=builder-vscode /tmp/local/ /opt/perl/local/
-
-FROM runnable-vscode AS vscode
-# This Dockerfile adds a non-root 'vscode' user with sudo access. However, for Linux,
-# this user's GID/UID must match your local user UID/GID to avoid permission issues
-# with bind mounts. Update USER_UID / USER_GID if yours is not 1000. See
-# https://aka.ms/vscode-remote/containers/non-root-user for details.
-ARG USERNAME=vscode
-ARG USER_UID=1000
-ARG USER_GID=$USER_UID
-
-# Configure apt and install packages
-RUN install_packages apt-utils dialog 2>&1 \
- #
- # Verify git, process tools, lsb-release (common in install instructions for CLIs) installed
- && install_packages git iproute2 procps lsb-release \
- # Create a non-root user to use if preferred - see https://aka.ms/vscode-remote/containers/non-root-user.
- && groupadd --gid $USER_GID $USERNAME \
- && useradd -s /bin/bash --uid $USER_UID --gid $USER_GID -m $USERNAME \
- # [Optional] Add sudo support for the non-root user
- && install_packages sudo \
- && echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME\
- && chmod 0440 /etc/sudoers.d/$USERNAME
-
-FROM runnable-vscode AS perldb
-
-# Readline support for the Perl debugger
-RUN install_packages libterm-readline-gnu-perl libterm-readkey-perl
-
-FROM runnable AS withsrc
-
-# Install Product Opener from the workdir
-COPY . /opt/product-opener/
-WORKDIR /opt/product-opener
+######################
+# Prod image is default
+######################
+FROM runnable as prod
diff --git a/Dockerfile.frontend b/Dockerfile.frontend
index 8180e6d142187..f101662c9aa68 100644
--- a/Dockerfile.frontend
+++ b/Dockerfile.frontend
@@ -1,21 +1,41 @@
-FROM node:lts as builder
+# syntax = docker/dockerfile:1.2
+# Base user uid / gid keep 1000 on prod, align with your user on dev
+ARG USER_UID=1000
+ARG USER_GID=1000
-RUN mkdir -p /opt/product-opener/node_modules
-COPY package*.json /opt/product-opener/
-COPY .snyk /opt/product-opener/
+FROM node:lts as builder
+ARG USER_UID
+ARG USER_GID
+RUN usermod --uid $USER_UID node && \
+ groupmod --gid $USER_GID node && \
+ mkdir -p /opt/product-opener/node_modules && \
+ mkdir -p /opt/product-opener/html/data && \
+ mkdir -p /opt/product-opener/html/css/dist && \
+ mkdir -p /opt/product-opener/html/images/icons/dist && \
+ mkdir -p /opt/product-opener/html/js/dist && \
+ mkdir -p /opt/product-opener/html/images/products && \
+ chown node:node -R /opt/product-opener/
+COPY --chown=node:node package*.json /opt/product-opener/
+COPY --chown=node:node .snyk /opt/product-opener/
WORKDIR /opt/product-opener
-RUN npm install
+USER node
+RUN --mount=type=cache,id=npm-cache,target=/root/.npm npm install
ENV PATH /opt/product-opener/node_modules/.bin:$PATH
-COPY html /opt/product-opener/html
-COPY icons /opt/product-opener/icons
-COPY scss /opt/product-opener/scss
-COPY gulpfile.js /opt/product-opener/
+COPY --chown=node:node html /opt/product-opener/html
+COPY --chown=node:node icons /opt/product-opener/icons
+COPY --chown=node:node scss /opt/product-opener/scss
+COPY --chown=node:node gulpfile.js /opt/product-opener/
+COPY --chown=node:node .snyk /opt/product-opener/
# https://github.com/openfoodfacts/openfoodfacts-server/pull/5544#issuecomment-914221199
RUN find . -xtype l | xargs -I {} sh -c "origin=\$(readlink {} | tr '\\\\\\\\' '/') && ln -sf \$origin {}"
RUN npm run build
-FROM nginx:stable-alpine
+FROM nginx:stable
WORKDIR /opt/product-opener
+ARG USER_UID
+ARG USER_GID
+RUN usermod -u $USER_UID www-data && \
+ groupmod --gid $USER_GID www-data
COPY --from=builder /opt/product-opener/html/ /opt/product-opener/html/
-COPY --from=builder /opt/product-opener/node_modules/ /opt/product-opener/node_modules/
+COPY --from=builder /opt/product-opener/node_modules/ /opt/product-opener/node_modules/
\ No newline at end of file
diff --git a/Makefile b/Makefile
index 6048b353ef435..cd29306fe58ed 100644
--- a/Makefile
+++ b/Makefile
@@ -3,7 +3,13 @@
NAME = "ProductOpener"
ENV_FILE ?= .env
MOUNT_POINT ?= /mnt
+DOCKER_LOCAL_DATA ?= /srv/off/docker_data
HOSTS=127.0.0.1 world.productopener.localhost fr.productopener.localhost static.productopener.localhost ssl-api.productopener.localhost fr-en.productopener.localhost
+export DOCKER_BUILDKIT=1
+export COMPOSE_DOCKER_CLI_BUILD=1
+UID ?= $(shell id -u)
+export USER_UID:=${UID}
+
DOCKER_COMPOSE=docker-compose --env-file=${ENV_FILE}
.DEFAULT_GOAL := dev
@@ -27,7 +33,7 @@ goodbye:
#-------#
# Local #
#-------#
-dev: hello up setup_incron import_sample_data refresh_product_tags
+dev: hello init_backend up import_sample_data refresh_product_tags
@echo "🥫 You should be able to access your local install of Open Food Facts at http://productopener.localhost"
@echo "🥫 You have around 100 test products. Please run 'make import_prod_data' if you want a full production dump (~2M products)."
@@ -52,6 +58,7 @@ edit_etc_hosts:
up:
@echo "🥫 Building and starting containers …"
${DOCKER_COMPOSE} up -d --build 2>&1
+ @echo "🥫 started service at http://openfoodfacts.localhost"
down:
@echo "🥫 Bringing down containers …"
@@ -66,6 +73,7 @@ reset: hdown up
restart:
@echo "🥫 Restarting frontend & backend containers …"
${DOCKER_COMPOSE} restart backend frontend
+ @echo "🥫 started service at http://openfoodfacts.localhost"
restart_db:
@echo "🥫 Restarting MongoDB database …"
@@ -87,12 +95,22 @@ tail:
@echo "🥫 Reading logs (Apache2, Nginx) …"
tail -f logs/**/*
-setup_incron:
- @echo "🥫 Setting up incron jobs defined in conf/incron.conf …"
- ${DOCKER_COMPOSE} exec -T backend sh -c "\
- echo 'root' >> /etc/incron.allow && \
- incrontab -u root /opt/product-opener/conf/incron.conf && \
- incrond"
+
+#----------#
+# Services #
+#----------#
+build_lang:
+ @echo "🥫 Rebuild language"
+ # Run build_lang.pl
+ ${DOCKER_COMPOSE} run --rm backend perl -I/opt/product-opener/lib -I/opt/perl/local/lib/perl5 /opt/product-opener/scripts/build_lang.pl
+
+# use this in dev if you messed up with permissions or user uid/gid
+reset_owner:
+ @echo "🥫 reset owner"
+ ${DOCKER_COMPOSE} run --rm --no-deps --user root backend chown www-data:www-data -R /opt/product-opener/ /mnt/podata /var/log/apache2 /var/log/httpd || true
+ ${DOCKER_COMPOSE} run --rm --no-deps --user root frontend chown www-data:www-data -R /opt/product-opener/html/images/icons/dist /opt/product-opener/html/js/dist /opt/product-opener/html/css/dist
+
+init_backend: build_lang
refresh_product_tags:
@echo "🥫 Refreshing products tags (update MongoDB products_tags collection) …"
@@ -101,7 +119,7 @@ refresh_product_tags:
import_sample_data:
@echo "🥫 Importing sample data (~100 products) into MongoDB …"
- ${DOCKER_COMPOSE} exec --user=www-data backend bash /opt/product-opener/scripts/import_sample_data.sh
+ ${DOCKER_COMPOSE} run --rm backend bash /opt/product-opener/scripts/import_sample_data.sh
import_prod_data:
@echo "🥫 Importing production data (~2M products) into MongoDB …"
@@ -123,16 +141,23 @@ front_lint:
checks: front_lint
+tests:
+ @echo "🥫 Runing tests …"
+ docker-compose run --rm backend prove -l
+
#------------#
# Production #
#------------#
create_external_volumes:
@echo "🥫 Creating external volumes (production only) …"
+ # zfs replications
docker volume create --driver=local -o type=none -o o=bind -o device=${MOUNT_POINT}/data html_data
docker volume create --driver=local -o type=none -o o=bind -o device=${MOUNT_POINT}/users users
docker volume create --driver=local -o type=none -o o=bind -o device=${MOUNT_POINT}/products products
docker volume create --driver=local -o type=none -o o=bind -o device=${MOUNT_POINT}/product_images product_images
docker volume create --driver=local -o type=none -o o=bind -o device=${MOUNT_POINT}/orgs orgs
+ # local data
+ docker volume create --driver=local -o type=none -o o=bind -o device=${DOCKER_LOCAL_DATA}/podata podata
#---------#
# Cleanup #
@@ -146,11 +171,11 @@ prune_cache:
docker builder prune -f
clean_folders:
- rm html/images/products
- rm -rf node_modules/
- rm -rf html/data/i18n/
- rm -rf html/{css,js}/dist/
- rm -rf tmp/
- rm -rf logs/
+ ( rm html/images/products || true )
+ ( rm -rf node_modules/ || true )
+ ( rm -rf html/data/i18n/ || true )
+ ( rm -rf html/{css,js}/dist/ || true )
+ ( rm -rf tmp/ || true )
+ ( rm logs/* logs/apache2/* logs/nginx/* || true )
clean: goodbye hdown prune prune_cache clean_folders
diff --git a/cgi/css.pl b/cgi/css.pl
new file mode 100644
index 0000000000000..a2233de922ac0
--- /dev/null
+++ b/cgi/css.pl
@@ -0,0 +1,50 @@
+#!/usr/bin/perl -w
+
+# This file is part of Product Opener.
+#
+# Product Opener
+# Copyright (C) 2011-2020 Association Open Food Facts
+# Contact: contact@openfoodfacts.org
+# Address: 21 rue des Iles, 94100 Saint-Maur des Fossés, France
+#
+# Product Opener is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see
Open Food Facts is 100% free and independent of the food industry. We need your help to continue and to grow the project.
Open Food Facts is 100% free and independent of the food industry. We need your help to continue and to grow the project.
The donation form is being loaded.
You can also access it by clicking here.
The donation form is being loaded.
You can also access it by clicking here.
Open Food Facts is 100% free and independent of the food industry. We need your help to continue and to grow the project.
Open Food Facts is 100% free and independent of the food industry. We need your help to continue and to grow the project.
The donation form is being loaded.
You can also access it by clicking here.
The donation form is being loaded.
You can also access it by clicking here.
- crwdns147868:0crwdne147868:0 + crwdns172172:0crwdne172172:0
- crwdns147870:0crwdne147870:0 + crwdns172174:0crwdne172174:0
Open Food Facts is 100% free and independent of the food industry. We need your help to continue and to grow the project.
+Open Food Facts yra 100% nemokama ir nepriklausoma nuo maisto pramonės. Mums reikia jūsų pagalbos, kad tęstume ir plėtotume projektą.
Open Food Facts is 100% free and independent of the food industry. We need your help to continue and to grow the project.
+Open Food Facts yra 100% nemokama ir nepriklausoma nuo maisto pramonės. Mums reikia jūsų pagalbos, kad tęstume ir plėtotume projektą.
The donation form is being loaded.
You can also access it by clicking here.
The donation form is being loaded.
You can also access it by clicking here.
- Technology: Development, maintenance, servers to keep the - database growing and to add cool new features to the Open Food - Facts mobile app and web site. + Technologijos: kūrimas, priežiūra, serveriai, siekiant išlaikyti + duomenų bazių augimą ir pridėti naujų šaunių funkcijų į Open Food + Facts mobiliąją programėlę ir svetainę.
- People and projects: To give our best support to the Open - Food Facts community, to work with researchers, and to make our - food products data have the biggest impact on our health, our - planet, and society. + Žmonės ir projektai: Siekiame kuo geriau paremti „Open + Food Facts“ bendruomenę, bendradarbiauti su tyrėjais ir padaryti, kad mūsų + maisto produktų duomenys turėtų didžiausią įtaką mūsų sveikatai, + mūsų planetai ir visuomenei.
Open Food Facts is 100% free and independent of the food industry. We need your help to continue and to grow the project.
Open Food Facts is 100% free and independent of the food industry. We need your help to continue and to grow the project.
The donation form is being loaded.
You can also access it by clicking here.
The donation form is being loaded.
You can also access it by clicking here.
Open Food Facts is 100% free and independent of the food industry. We need your help to continue and to grow the project.
Open Food Facts is 100% free and independent of the food industry. We need your help to continue and to grow the project.
The donation form is being loaded.
You can also access it by clicking here.
The donation form is being loaded.
You can also access it by clicking here.
Open Food Facts is 100% free and independent of the food industry. We need your help to continue and to grow the project.
Open Food Facts is 100% free and independent of the food industry. We need your help to continue and to grow the project.
The donation form is being loaded.
You can also access it by clicking here.
The donation form is being loaded.
You can also access it by clicking here.
Open Food Facts is 100% free and independent of the food industry. We need your help to continue and to grow the project.
Open Food Facts is 100% free and independent of the food industry. We need your help to continue and to grow the project.
The donation form is being loaded.
You can also access it by clicking here.
The donation form is being loaded.
You can also access it by clicking here.
Open Food Facts is 100% free and independent of the food industry. We need your help to continue and to grow the project.
Open Food Facts is 100% free and independent of the food industry. We need your help to continue and to grow the project.
The donation form is being loaded.
You can also access it by clicking here.
The donation form is being loaded.
You can also access it by clicking here.
Open Food Facts is 100% free and independent of the food industry. We need your help to continue and to grow the project.
Open Food Facts is 100% free and independent of the food industry. We need your help to continue and to grow the project.
The donation form is being loaded.
You can also access it by clicking here.
The donation form is being loaded.
You can also access it by clicking here.
Open Food Facts is 100% free and independent of the food industry. We need your help to continue and to grow the project.
Open Food Facts is 100% free and independent of the food industry. We need your help to continue and to grow the project.
The donation form is being loaded.
You can also access it by clicking here.
The donation form is being loaded.
You can also access it by clicking here.
Open Food Facts is 100% free and independent of the food industry. We need your help to continue and to grow the project.
Open Food Facts is 100% free and independent of the food industry. We need your help to continue and to grow the project.
The donation form is being loaded.
You can also access it by clicking here.
The donation form is being loaded.
You can also access it by clicking here.
Open Food Facts is 100% free and independent of the food industry. We need your help to continue and to grow the project.
Open Food Facts is 100% free and independent of the food industry. We need your help to continue and to grow the project.
The donation form is being loaded.
You can also access it by clicking here.
The donation form is being loaded.
You can also access it by clicking here.
Open Food Facts is 100% free and independent of the food industry. We need your help to continue and to grow the project.
Open Food Facts is 100% free and independent of the food industry. We need your help to continue and to grow the project.
Thank you,
- Anca, Florence, Léonore, Sylvia, Charles, Christian, Ludovic, Pierre, + Anca, Florence, Léonore, Marie, Sylvia, Charles, Christian, Ludovic, Pierre, Sébastien, Stéphane, Vincent and the whole Open Food Facts team
The donation form is being loaded.
You can also access it by clicking here.
The donation form is being loaded.
You can also access it by clicking here.
Open Food Facts is 100% free and independent of the food industry. We need your help to continue and to grow the project.
Open Food Facts is 100% free and independent of the food industry. We need your help to continue and to grow the project.
The donation form is being loaded.
You can also access it by clicking here.
The donation form is being loaded.
You can also access it by clicking here.
Open Food Facts is 100% free and independent of the food industry. We need your help to continue and to grow the project.
Open Food Facts is 100% free and independent of the food industry. We need your help to continue and to grow the project.
The donation form is being loaded.
You can also access it by clicking here.
The donation form is being loaded.
You can also access it by clicking here.
Open Food Facts is 100% free and independent of the food industry. We need your help to continue and to grow the project.
Open Food Facts is 100% free and independent of the food industry. We need your help to continue and to grow the project.
Thank you,
- Anca, Florence, Léonore, Sylvia, Charles, Christian, Ludovic, Pierre, + Anca, Florence, Léonore, Marie, Sylvia, Charles, Christian, Ludovic, Pierre, Sébastien, Stéphane, Vincent and the whole Open Food Facts team
The donation form is being loaded.
You can also access it by clicking here.
The donation form is being loaded.
You can also access it by clicking here.
Open Food Facts is 100% free and independent of the food industry. We need your help to continue and to grow the project.
Open Food Facts is 100% free and independent of the food industry. We need your help to continue and to grow the project.
The donation form is being loaded.
You can also access it by clicking here.
The donation form is being loaded.
You can also access it by clicking here.
Open Food Facts is 100% free and independent of the food industry. We need your help to continue and to grow the project.
Open Food Facts is 100% free and independent of the food industry. We need your help to continue and to grow the project.
The donation form is being loaded.
You can also access it by clicking here.
The donation form is being loaded.
You can also access it by clicking here.