From f148af2bf0b549c9f358ed5b798cd79a94f6bbfe Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Th=C3=A9o?= <theo@le-filament.com>
Date: Thu, 27 Oct 2022 16:09:10 +0200
Subject: [PATCH] [ADD] image from scratch

---
 .gitlab-ci.yml          |   6 +-
 16.0-alpine.Dockerfile  |  71 -------------
 16.0-scratch.Dockerfile | 220 ++++++++++++++++++++++++++++++++++++++++
 entrypoint-scratch.sh   |  87 ++++++++++++++++
 4 files changed, 310 insertions(+), 74 deletions(-)
 delete mode 100644 16.0-alpine.Dockerfile
 create mode 100644 16.0-scratch.Dockerfile
 create mode 100755 entrypoint-scratch.sh

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index e99942c..769ce96 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -66,7 +66,7 @@ docker-build-16.0:
   - docker push "$CI_REGISTRY_IMAGE:16.0"
   only:
   - '16.0'
-docker-build-16.0-alpine:
+docker-build-16.0-scratch:
   image: docker:20.10.17
   stage: build
   services:
@@ -74,8 +74,8 @@ docker-build-16.0-alpine:
   before_script:
   - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
   script:
-  - docker build --pull -f 16.0-alpine.Dockerfile -t "$CI_REGISTRY_IMAGE:16.0-alpine"
+  - docker build --pull -f 16.0-scratch.Dockerfile -t "$CI_REGISTRY_IMAGE:16.0-scratch"
     .
-  - docker push "$CI_REGISTRY_IMAGE:16.0-alpine"
+  - docker push "$CI_REGISTRY_IMAGE:16.0-scratch"
   only:
   - '16.0'
diff --git a/16.0-alpine.Dockerfile b/16.0-alpine.Dockerfile
deleted file mode 100644
index 55d4504..0000000
--- a/16.0-alpine.Dockerfile
+++ /dev/null
@@ -1,71 +0,0 @@
-FROM surnet/alpine-wkhtmltopdf:3.16.0-0.12.6-small as wkhtmltopdf
-
-FROM python:3.10-alpine AS builder
-RUN set -x; \
-        apk add --no-cache python3-dev libffi-dev gcc musl-dev make postgresql-dev openldap-dev cyrus-sasl-dev jpeg-dev zlib-dev libsass-dev g++ &&\
-        pip install wheel &&\
-        echo 'INPUT ( libldap.so )' > /usr/lib/libldap_r.so &&\
-        pip wheel --wheel-dir=/svc/wheels -r https://raw.githubusercontent.com/odoo/odoo/master/requirements.txt &&\
-        pip wheel --wheel-dir=/svc/wheels phonenumbers simplejson openupgradelib PyYAML
-
-
-FROM python:3.10-alpine AS final
-ENV LANG=C.UTF-8 \
-    LC_ALL=C.UTF-8 \
-    PGDATABASE=odoo
-
-RUN set -x; \
-        apk add --no-cache \
-            bash \
-           	fontconfig \
-            freetype \
-            git \
-            libjpeg-turbo \
-            libsass \
-            libstdc++ \
-            libx11 \
-           	libxrender \
-            postgresql-client
-
-# Copy wkhtmltopdf files from docker-wkhtmltopdf image
-COPY --from=wkhtmltopdf /bin/wkhtmltopdf /bin/wkhtmltopdf
-
-COPY --from=builder /svc /svc
-RUN pip3 install --no-index --find-links=/svc/wheels -r https://raw.githubusercontent.com/odoo/odoo/master/requirements.txt &&\
-        pip3 install --no-index --find-links=/svc/wheels phonenumbers simplejson openupgradelib PyYAML
-
-# Add Git Known Hosts
-COPY ./ssh_known_git_hosts /root/.ssh/known_hosts
-
-# Install Odoo and remove not French translations and .git directory to limit amount of data used by container
-RUN set -x; \
-        adduser -h /opt/odoo -D odoo &&\
-        /bin/bash -c "mkdir -p /opt/odoo/{etc,odoo,additional_addons,private_addons,data,private}" &&\
-        git clone -b 16.0 --depth 1 https://github.com/OCA/OCB.git /opt/odoo/odoo &&\
-        rm -rf /opt/odoo/odoo/.git &&\
-        find /opt/odoo/odoo/addons/*/i18n/ /opt/odoo/odoo/odoo/addons/base/i18n/ -type f -not -name 'fr.po' -delete &&\
-        chown -R odoo:odoo /opt/odoo
-
-# Copy entrypoint script and Odoo configuration file
-COPY ./entrypoint.sh /
-COPY ./odoo.conf /opt/odoo/etc/odoo.conf
-RUN chown odoo:odoo /opt/odoo/etc/odoo.conf
-
-# Mount /opt/odoo/data to allow restoring filestore
-VOLUME ["/opt/odoo/data/"]
-
-# Expose Odoo services
-EXPOSE 8069
-
-# Set default user when running the container
-USER odoo
-
-# Start
-ENTRYPOINT ["/entrypoint.sh"]
-CMD ["odoo"]
-
-# Metadata
-LABEL org.label-schema.schema-version="16.0" \
-      org.label-schema.vendor=LeFilament \
-      org.label-schema.license=Apache-2.0 \
-      org.label-schema.vcs-url="https://sources.le-filament.com/lefilament/odoo_docker"
diff --git a/16.0-scratch.Dockerfile b/16.0-scratch.Dockerfile
new file mode 100644
index 0000000..46e59a9
--- /dev/null
+++ b/16.0-scratch.Dockerfile
@@ -0,0 +1,220 @@
+FROM surnet/alpine-wkhtmltopdf:3.16.0-0.12.6-small as wkhtmltopdf
+
+
+FROM alpine as build
+
+# Initial setup of new root.
+RUN apk update \
+    && mkdir --parents \
+        /newroot/etc \
+        /newroot/bin \
+        /newroot/usr/bin \
+    && cp -a --parents \
+        /bin/busybox \
+        /lib/ld-musl* \
+        /newroot/ \
+    && /bin/busybox --install -s /newroot/bin/ \
+    && /bin/busybox --install -s /newroot/usr/bin/ \
+    && echo 'root:x:0:0:::' > /newroot/etc/passwd \
+    && echo 'root:x:0:' > /newroot/etc/group
+
+# Add depedencies
+RUN apk add --no-cache \
+        file \
+        freetype-dev \
+        g++ \
+        gcc \
+        git \
+        jpeg-dev \
+        libev-dev \
+        libffi-dev \
+        libx11-dev \
+        libxrender-dev \
+        fontconfig-dev \
+        make \
+        musl-dev \
+        openldap-dev \
+        postgresql-dev \
+        py3-pip \
+        python3 \
+        python3-dev \
+        zlib-dev
+
+# Add Odoo.
+RUN git clone -b 16.0 --depth 1 https://github.com/OCA/OCB.git /newroot/opt/odoo/odoo \
+    && rm -rf /newroot/opt/odoo/odoo/.git \
+    && find /newroot/opt/odoo/odoo/addons/*/i18n/ /newroot/opt/odoo/odoo/odoo/addons/base/i18n/ -type f -not -name 'fr.po' -delete
+
+## Add Git known hosts.
+#COPY ./ssh_known_git_hosts /root/.ssh/known_hosts
+#
+## Install Odoo OCA and Le Filament default dependencies.
+#RUN mkdir -p \
+#        /tmp/oca-repos/ \
+#        /newroot/opt/odoo/additional_addons \
+#        /newroot/opt/odoo/private_addons \
+#    && git clone -b 16.0 --depth 1 \
+#        https://github.com/OCA/account-financial-reporting.git \
+#        /tmp/oca-repos/account-financial-reporting \
+#    && mv /tmp/oca-repos/account-financial-reporting/account_tax_balance \
+#        /newroot/opt/odoo/additional_addons/ \
+#    && git clone -b 16.0 --depth 1 \
+#        https://github.com/OCA/account-financial-tools.git \
+#        /tmp/oca-repos/account-financial-tools \
+#    && mv /tmp/oca-repos/account-financial-tools/account_lock_date_update \
+#        /tmp/oca-repos/account-financial-tools/account_move_name_sequence \
+#        /tmp/oca-repos/account-financial-tools/account_reconcile_show_boolean \
+#        /newroot/opt/odoo/additional_addons/ \
+#    && git clone -b 16.0 --depth 1 \
+#        https://github.com/OCA/account-invoicing.git \
+#        /tmp/oca-repos/account-invoicing \
+#    && mv /tmp/oca-repos/account-invoicing/sale_timesheet_invoice_description \
+#        /newroot/opt/odoo/additional_addons/ \
+#    && git clone -b 16.0 --depth 1 \
+#        https://github.com/OCA/account-reconcile.git \
+#        /tmp/oca-repos/account-reconcile \
+#    && mv /tmp/oca-repos/account-reconcile/account_reconciliation_widget \
+#        /newroot/opt/odoo/additional_addons/ \
+#    && git clone -b 16.0 --depth 1 \
+#        https://github.com/OCA/bank-statement-import.git \
+#        /tmp/oca-repos/bank-statement-import \
+#    && mv /tmp/oca-repos/bank-statement-import/account_statement_import \
+#        /tmp/oca-repos/bank-statement-import/account_statement_import_ofx \
+#        /newroot/opt/odoo/additional_addons/ \
+#    && git clone -b 16.0 --depth 1 \
+#        https://github.com/OCA/crm.git \
+#        /tmp/oca-repos/crm \
+#    && mv /tmp/oca-repos/crm/crm_stage_probability \
+#        /newroot/opt/odoo/additional_addons/ \
+#    && git clone -b 16.0 --depth 1 \
+#        https://github.com/OCA/partner-contact.git \
+#        /tmp/oca-repos/partner-contact \
+#    && mv /tmp/oca-repos/partner-contact/partner_disable_gravatar \
+#        /tmp/oca-repos/partner-contact/partner_firstname \
+#        /newroot/opt/odoo/additional_addons/ \
+#    && git clone -b 16.0 --depth 1 \
+#        https://github.com/OCA/project.git \
+#        /tmp/oca-repos/project \
+#    && mv /tmp/oca-repos/project/project_category \
+#        /tmp/oca-repos/project/project_status \
+#        /tmp/oca-repos/project/project_task_default_stage \
+#        /tmp/oca-repos/project/project_template \
+#        /tmp/oca-repos/project/project_timeline \
+#        /newroot/opt/odoo/additional_addons/ \
+#    && git clone -b 16.0 --depth 1 \
+#        https://github.com/OCA/server-auth.git \
+#        /tmp/oca-repos/server-auth \
+#    && mv /tmp/oca-repos/server-auth/password_security \
+#        /newroot/opt/odoo/additional_addons/ \
+#    && git clone -b 16.0 --depth 1 \
+#        https://github.com/OCA/server-brand.git \
+#        /tmp/oca-repos/server-brand \
+#    && mv /tmp/oca-repos/server-brand/disable_odoo_online \
+#        /tmp/oca-repos/server-brand/remove_odoo_enterprise \
+#        /newroot/opt/odoo/additional_addons/ \
+#    && git clone -b 16.0 --depth 1 \
+#        https://github.com/OCA/server-tools.git \
+#        /tmp/oca-repos/server-tools \
+#    && mv /tmp/oca-repos/server-tools/base_search_fuzzy \
+#        /tmp/oca-repos/server-tools/module_change_auto_install \
+#        /newroot/opt/odoo/additional_addons/ \
+#    && git clone -b 16.0 --depth 1 \
+#        https://github.com/OCA/server-ux.git \
+#        /tmp/oca-repos/server-ux \
+#    && mv /tmp/oca-repos/server-ux/base_technical_features \
+#        /tmp/oca-repos/server-ux/date_range \
+#        /tmp/oca-repos/server-ux/mass_editing \
+#        /newroot/opt/odoo/additional_addons/ \
+#    && git clone -b 16.0 --depth 1 \
+#        https://github.com/OCA/social.git \
+#        /tmp/oca-repos/social \
+#    && mv /tmp/oca-repos/social/base_search_mail_content \
+#        /tmp/oca-repos/social/mail_debrand \
+#        /tmp/oca-repos/social/mail_tracking \
+#        /newroot/opt/odoo/additional_addons/ \
+#    && git clone -b 16.0 --depth 1 \
+#        https://github.com/OCA/web.git \
+#        /tmp/oca-repos/web \
+#    && mv /tmp/oca-repos/web/web_environment_ribbon \
+#        /tmp/oca-repos/web/web_responsive \
+#        /tmp/oca-repos/web/web_no_bubble \
+#        /tmp/oca-repos/web/web_timeline \
+#        /newroot/opt/odoo/additional_addons/ \
+#    && rm -rf /tmp/oca-repos/ \
+#    && find /newroot/opt/odoo/additional_addons/*/i18n/ -type f -not -name 'fr.po' -delete \
+#    && git clone -b 16.0 --depth 1 \
+#        https://sources.le-filament.com/lefilament/remove_login_links.git \
+#        /newroot/opt/odoo/private_addons/remove_login_links \
+#    && git clone -b 16.0 --depth 1 \
+#        https://sources.le-filament.com/lefilament/lefilament_release_agent.git \
+#        /newroot/opt/odoo/private_addons/lefilament_release_agent
+
+# Fix a ldap library bug.
+RUN echo -n "INPUT ( libldap.so )" > /usr/lib/libldap_r.so
+
+# Install Python requirements.
+RUN pip install --requirement /newroot/opt/odoo/odoo/requirements.txt
+
+# Only copy libraries of needed binaries to new root.
+RUN ls \
+        /lib/libz.so* \
+        /usr/bin/python3* \
+        /usr/lib/libexpat.so* \
+        /usr/lib/libfontconfig.so* \
+        /usr/lib/libfreetype.so* \
+        /usr/lib/libjpeg.so* \
+        /usr/lib/libpq.so* \
+        /usr/lib/libpython3.so* \
+        /usr/lib/python3.10/lib-dynload/*.so \
+        /usr/lib/python3.10/site-packages/*.so \
+        /usr/lib/libX11.so* \
+        /usr/lib/libXrender.so* \
+        > to_copy \
+    && xargs -a to_copy -I R ldd R \
+    | tr -s '[:blank:]' '\n' \
+    | grep '^/' \
+    | sed 's/://' \
+    | sort -u \
+    | xargs cp -aL --parents -t /newroot/ \
+    && xargs -a to_copy cp -a --parents -t /newroot/
+
+# Copy Python libraries.
+RUN cp -a --parents \
+        /usr/lib/python3.10/ \
+        /newroot
+
+COPY --from=wkhtmltopdf /bin/wkhtmltopdf /newroot/bin/wkhtmltopdf
+COPY ./entrypoint-scratch.sh /newroot/entrypoint.sh
+
+# Add odoo user.
+RUN echo 'odoo:x:1:1:::' >> /newroot/etc/passwd \
+    && echo 'odoo:x:1:' >> /newroot/etc/group \
+    && chown -R 1:1 /newroot/opt/odoo/ \
+    && chmod 555 /newroot/entrypoint.sh \
+    && mkdir /newroot/tmp \
+    && chmod 1777 /newroot/tmp
+
+
+# Final image.
+FROM scratch
+
+COPY --from=build /newroot /
+
+# Mount /opt/odoo/data to allow restoring filestore.
+VOLUME ["/opt/odoo/data/"]
+
+# Expose Odoo services.
+EXPOSE 8069
+
+# Set default user when running the container.
+USER odoo
+
+# Start
+ENTRYPOINT ["/entrypoint.sh"]
+CMD ["odoo"]
+
+# Metadata
+LABEL org.label-schema.schema-version="16.0" \
+      org.label-schema.vendor=LeFilament \
+      org.label-schema.license=Apache-2.0 \
+      org.label-schema.vcs-url="https://sources.le-filament.com/lefilament/odoo_docker"
diff --git a/entrypoint-scratch.sh b/entrypoint-scratch.sh
new file mode 100755
index 0000000..d11e0b4
--- /dev/null
+++ b/entrypoint-scratch.sh
@@ -0,0 +1,87 @@
+#!/bin/sh
+
+# set the postgres database host, port, user and password according to the environment
+# and pass them as arguments to the odoo process if not present in the config file
+: ${HOST:=${DB_PORT_5432_TCP_ADDR:='db'}}
+: ${PORT:=${DB_PORT_5432_TCP_PORT:=5432}}
+: ${USER:=${DB_ENV_POSTGRES_USER:=${POSTGRES_USER:='odoo'}}}
+: ${PASSWORD:=${DB_ENV_POSTGRES_PASSWORD:=${POSTGRES_PASSWORD:='odoo'}}}
+
+check_config() {
+    param="$1"
+    value="$2"
+    if ! grep -q -E "^\s*\b${param}\b\s*=" /opt/odoo/etc/odoo.conf ; then
+        DB_ARGS="${DB_ARGS} --${param} ${value}"
+    fi;
+}
+
+unaccent_db() {
+    /usr/bin/python3 -c "import psycopg2
+
+try:
+    conn = psycopg2.connect(database='postgres', user='${USER}', password='${PASSWORD}', host='${HOST}', port='${PORT}')
+except:
+    print('err: init: fail to connect to database')
+    exit(11)
+
+cur = conn.cursor()
+try:
+    cur.execute(\"SELECT datname FROM pg_database WHERE datname='${PGDATABASE}'\")
+except:
+    print('err: init: fail to execute request')
+    cur.close()
+    conn.close()
+    exit(12)
+
+if not cur.fetchall():
+    cur.close()
+    conn.close()
+    exit(1)
+
+try:
+    cur.execute('CREATE EXTENSION IF NOT EXISTS unaccent')
+except:
+    print('err: init: fail to execute request')
+    cur.close()
+    conn.close()
+    exit(13)
+
+conn.commit()
+cur.close()
+conn.close()
+exit(0)"
+
+    return $?
+}
+
+DB_ARGS=''
+check_config "db_host" "$HOST"
+check_config "db_port" "$PORT"
+check_config "db_user" "$USER"
+check_config "db_password" "$PASSWORD"
+
+unaccent_db
+return_code=$?
+[ "$return_code" -gt 10 ] && exit 1
+if [ "$return_code" == 1 ]; then
+  	echo "info: init: database $PGDATABASE does not exist"
+  	DB_ARGS="${DB_ARGS} --load-language fr_FR"
+fi
+
+case "$1" in
+    -- | odoo)
+        shift
+        if [[ "$1" == "scaffold" ]] ; then
+            exec /opt/odoo/odoo/odoo-bin -c /opt/odoo/etc/odoo.conf "$@"
+        else
+            exec /opt/odoo/odoo/odoo-bin -c /opt/odoo/etc/odoo.conf "$@" ${DB_ARGS}
+        fi
+        ;;
+    -*)
+        exec /opt/odoo/odoo/odoo-bin -c /opt/odoo/etc/odoo.conf "$@" ${DB_ARGS}
+        ;;
+    *)
+        exec "$@"
+esac
+
+exit 1
-- 
GitLab