Super Slow to public application on Docker - docker

I researched everything and I can't find a solution.
I'm running the docker-compose compilation that takes 10 to 15 minutes to go up in production, it's crazy. I've tried everything, tried to erase the volume, tried to clean the entire system, changed the network connection, uninstalled / reinstalled the Docker, ran a complete docker system prune -a - nothing.
I don't know if it is because of this delay, but it seems that even the dns gets lost and cannot find the application after all this time. I have to press ctrl + f5 to load the new update.
But this time is driving me crazy, 15 minutes to get everything up.
I appreciate any help.
.yml:
version: '3'
volumes:
app-volume:
services:
nginx:
container_name: nginx
restart: always
build:
context: ./nginx/
dockerfile: ./Dockerfile
depends_on:
- app
volumes:
- app-volume:/app
env_file:
- ./nginx/.envs/nginx.env
ports:
- "80:80"
- "443:443"
app:
container_name: app
build:
context: ./app/
dockerfile: ./compose/production/Dockerfile
image: app
volumes:
# - ./app/:/app
- app-volume:/home/app
env_file:
- ./app/.envs/.production/app.env
app Dockefile:
FROM node:12-alpine as builder
WORKDIR /home/app
RUN apk update && \
apk add --no-cache python make g++ iputils
RUN npm install -g #angular/cli
COPY package*.json ./
COPY *.lock ./
RUN yarn install --unsafe-perm
COPY . .
ARG FORCE_BUILD_ENV=1
ARG ENV_BUILD=0
RUN export $(grep -v '^#' .envs/.production/app.env | xargs) && \
npm run build:env && \
ls -lah && \
cat ./src/environments/environment.ts && \
cat ./src/environments/environment.prod.ts
CMD ["ng", "build", "--prod", "--outputPath=dist"]
nginx/Dockerfile:
FROM alpine:3.10
LABEL maintainer="NGINX Docker Maintainers <docker-maint#nginx.com>"
ENV NGINX_VERSION 1.16.1
ENV NGX_BROTLI_COMMIT e505dce68acc190cc5a1e780a3b0275e39f160ca
RUN GPG_KEYS=B0F4253373F8F6F510D42178520A9993A1C052F8 \
&& CONFIG="\
--prefix=/etc/nginx \
--sbin-path=/usr/sbin/nginx \
--modules-path=/usr/lib/nginx/modules \
--conf-path=/etc/nginx/nginx.conf \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--pid-path=/var/run/nginx.pid \
--lock-path=/var/run/nginx.lock \
--http-client-body-temp-path=/var/cache/nginx/client_temp \
--http-proxy-temp-path=/var/cache/nginx/proxy_temp \
--http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \
--http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \
--http-scgi-temp-path=/var/cache/nginx/scgi_temp \
--user=nginx \
--group=nginx \
--with-http_ssl_module \
--with-http_realip_module \
--with-http_addition_module \
--with-http_sub_module \
--with-http_dav_module \
--with-http_flv_module \
--with-http_mp4_module \
--with-http_gunzip_module \
--with-http_gzip_static_module \
--with-http_random_index_module \
--with-http_secure_link_module \
--with-http_stub_status_module \
--with-http_auth_request_module \
--with-http_xslt_module=dynamic \
--with-http_image_filter_module=dynamic \
--with-http_geoip_module=dynamic \
--with-http_perl_module=dynamic \
--with-threads \
--with-stream \
--with-stream_ssl_module \
--with-stream_ssl_preread_module \
--with-stream_realip_module \
--with-stream_geoip_module=dynamic \
--with-http_slice_module \
--with-mail \
--with-mail_ssl_module \
--with-compat \
--with-file-aio \
--with-http_v2_module \
--add-module=/usr/src/ngx_brotli \
" \
&& addgroup -S nginx \
&& adduser -D -S -h /var/cache/nginx -s /sbin/nologin -G nginx nginx \
&& apk add --no-cache --virtual .build-deps \
gcc \
libc-dev \
make \
openssl-dev \
pcre-dev \
zlib-dev \
linux-headers \
curl \
gnupg1 \
libxslt-dev \
gd-dev \
geoip-dev \
perl-dev \
&& apk add --no-cache --virtual .brotli-build-deps \
autoconf \
libtool \
automake \
git \
g++ \
cmake \
&& mkdir -p /usr/src \
&& cd /usr/src \
&& git clone --recursive https://github.com/google/ngx_brotli.git \
&& cd ngx_brotli \
&& git checkout -b $NGX_BROTLI_COMMIT $NGX_BROTLI_COMMIT \
&& cd .. \
&& curl -fSL https://nginx.org/download/nginx-$NGINX_VERSION.tar.gz -o nginx.tar.gz \
&& curl -fSL https://nginx.org/download/nginx-$NGINX_VERSION.tar.gz.asc -o nginx.tar.gz.asc \
&& sha512sum nginx.tar.gz nginx.tar.gz.asc \
&& export GNUPGHOME="$(mktemp -d)" \
&& gpg --keyserver ipv4.pool.sks-keyservers.net --recv-keys "$GPG_KEYS" \
&& gpg --batch --verify nginx.tar.gz.asc nginx.tar.gz \
&& rm -rf "$GNUPGHOME" nginx.tar.gz.asc \
&& mkdir -p /usr/src \
&& tar -zxC /usr/src -f nginx.tar.gz \
&& rm nginx.tar.gz \
&& cd /usr/src/nginx-$NGINX_VERSION \
&& ./configure $CONFIG --with-debug \
&& make -j$(getconf _NPROCESSORS_ONLN) \
&& mv objs/nginx objs/nginx-debug \
&& mv objs/ngx_http_xslt_filter_module.so objs/ngx_http_xslt_filter_module-debug.so \
&& mv objs/ngx_http_image_filter_module.so objs/ngx_http_image_filter_module-debug.so \
&& mv objs/ngx_http_geoip_module.so objs/ngx_http_geoip_module-debug.so \
&& mv objs/ngx_http_perl_module.so objs/ngx_http_perl_module-debug.so \
&& mv objs/ngx_stream_geoip_module.so objs/ngx_stream_geoip_module-debug.so \
&& ./configure $CONFIG \
&& make -j$(getconf _NPROCESSORS_ONLN) \
&& make install \
&& rm -rf /etc/nginx/html/ \
&& mkdir /etc/nginx/conf.d/ \
&& mkdir -p /usr/share/nginx/html/ \
&& install -m644 html/index.html /usr/share/nginx/html/ \
&& install -m644 html/50x.html /usr/share/nginx/html/ \
&& install -m755 objs/nginx-debug /usr/sbin/nginx-debug \
&& install -m755 objs/ngx_http_xslt_filter_module-debug.so /usr/lib/nginx/modules/ngx_http_xslt_filter_module-debug.so \
&& install -m755 objs/ngx_http_image_filter_module-debug.so /usr/lib/nginx/modules/ngx_http_image_filter_module-debug.so \
&& install -m755 objs/ngx_http_geoip_module-debug.so /usr/lib/nginx/modules/ngx_http_geoip_module-debug.so \
&& install -m755 objs/ngx_http_perl_module-debug.so /usr/lib/nginx/modules/ngx_http_perl_module-debug.so \
&& install -m755 objs/ngx_stream_geoip_module-debug.so /usr/lib/nginx/modules/ngx_stream_geoip_module-debug.so \
&& ln -s ../../usr/lib/nginx/modules /etc/nginx/modules \
&& strip /usr/sbin/nginx* \
&& strip /usr/lib/nginx/modules/*.so \
&& rm -rf /usr/src/nginx-$NGINX_VERSION \
&& rm -rf /usr/src/ngx_brotli \
\
# Bring in gettext so we can get `envsubst`, then throw
# the rest away. To do this, we need to install `gettext`
# then move `envsubst` out of the way so `gettext` can
# be deleted completely, then move `envsubst` back.
&& apk add --no-cache --virtual .gettext gettext \
&& mv /usr/bin/envsubst /tmp/ \
\
&& runDeps="$( \
scanelf --needed --nobanner /usr/sbin/nginx /usr/lib/nginx/modules/*.so /tmp/envsubst \
| awk '{ gsub(/,/, "\nso:", $2); print "so:" $2 }' \
| sort -u \
| xargs -r apk info --installed \
| sort -u \
)" \
&& apk add --no-cache --virtual .nginx-rundeps tzdata $runDeps \
&& apk del .build-deps \
&& apk del .brotli-build-deps \
&& apk del .gettext \
&& mv /tmp/envsubst /usr/local/bin/ \
\
# forward request and error logs to docker log collector
&& ln -sf /dev/stdout /var/log/nginx/access.log \
&& ln -sf /dev/stderr /var/log/nginx/error.log
RUN echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories && \
apk update && \
apk add --no-cache openssl brotli vim && \
rm -rf /var/cache/apk/*
RUN mkdir -p /etc/ssl/certs/private/
COPY ./server.crt /etc/ssl/certs/private/siap.crt
COPY ./server.key /etc/ssl/certs/private/siap.key
RUN openssl dhparam -out /etc/ssl/certs/private/dhparam.pem 4096
RUN rm -rf /etc/nginx/conf.d/*
COPY ./scripts/nginx.conf /etc/nginx/nginx.conf
COPY ./scripts/conf.d/brotli.conf /etc/nginx/conf.d/brotli.conf
COPY ./scripts/conf.d/siap.http.conf /etc/nginx/conf.d/siap.http.conf
COPY ./scripts/conf.d/siap.https.conf /etc/nginx/conf.d/siap.https.conf
COPY .envs ./.envs
RUN export $(grep -v '^#' .envs/nginx.env | xargs) && \
sed -i '2s/^.*$/ server '$SERVER_ENDERECO';/g' /etc/nginx/conf.d/siap.https.conf;
EXPOSE 80
STOPSIGNAL SIGTERM
RUN head /etc/nginx/conf.d/siap.https.conf
# RUN nginx -t
CMD ["nginx", "-g", "daemon off;"]

You're rebuilding your application every time you start the container stack. While I wouldn't expect this to usually take 10+ minutes, it's better to build the application just once and built it into a Docker image that can be reused.
You can use a multi-stage build to build the application into static files, and then package it into an Nginx server. The Dockerfile you show is actually most of the way there. You need to change the final CMD to a RUN so it runs during the build, and then add the additional stage to COPY the files into an nginx-based image:
FROM node:12-alpine AS builder
WORKDIR /home/app
... exactly what is in the question ...
RUN ["ng", "build", "--prod", "--outputPath=dist"] # not CMD
FROM alpine:3.10 AS server
... the existing nginx/Dockerfile ...
FROM server
COPY --from=builder /home/app/dist /usr/share/nginx/html
With the extended nginx/Dockerfile in the question, you'll need to do a little bit of additional work to combine these together. You need to COPY files from both the nginx and app subtrees. To make this work, you need to move the Dockerfile up to the top level of your directory tree, and when you COPY files into the image, you need to COPY app/package*.json or COPY nginx/scripts/nginx.conf from one of the subdirectories.
In your docker-compose.yml file, then, you can remove the service that's only used to build files, since this is included in the image-build sequence. You can also remove the volume, again since the compiled application is included in the image.
version: '3.8'
services:
nginx:
build: . # Dockerfile needs to COPY app/... and COPY nginx/...
restart: always
env_file:
- ./nginx/.envs/nginx.env
ports:
- "80:80"
- "443:443"
# no volumes:; do not need to override container_name:
# no app: container
# no top-level volumes:
You can do even better than this in production. If you have access to a Docker registry -- Docker Hub, something your cloud provider offers, something you run yourself -- you can build this image separately, run whatever integration tests you need, and then push it to the registry. Instead of build:, set image: to point to the specific tagged image you need (it's good practice to use a different tag for each build).
services:
nginx:
image: my/nginx:20210524
# no build:
restart: always
env_file: [...]
ports: [...]
Now when you go to do a deploy, build, tag, and push the image, maybe using a CI system for automation. Once you've pushed the image, log into the production machine and change image: to point to the new build, and run docker-compose pull; docker-compose up -d. Compose will pull the updated image and then recreate the container using it. The image contains the prebuilt application, and you pulled it while the old container was already running, so there should be almost no downtime to do this update.

Related

Running NGINX UNIT in Docker: Unit is running unprivileged, then it cannot use arbitrary user and group

The error I get is this:
/usr/local/bin/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, launching Unit daemon to perform initial configuration... 2022/08/31 17:30:45
[warn] 11#11 Unit is running unprivileged, then it cannot use arbitrary user and group. 2022/08/31 17:30:45
[alert] 11#11 Unable to create certificates storage directory: mkdir(/var/lib/unit/certs/) failed (13: Permission denied) 2022/08/31 17:30:45 [alert] 11#11 bind(6, unix:/var/run/control.unit.sock.tmp) failed (13: Permission denied)
This is my Dockerfile:
FROM node:16 as BUILDER
LABEL maintainer="NGINX Docker Maintainers <docker-maint#nginx.com>"
USER root
RUN set -ex \
&& apt-get update \
&& apt-get install --no-install-recommends --no-install-suggests -y ca-certificates mercurial build-essential libssl-dev libpcre2-dev \
&& mkdir -p /usr/lib/unit/modules /usr/lib/unit/debug-modules \
&& hg clone https://hg.nginx.org/unit \
&& cd unit \
&& hg up 1.27.0 \
&& NCPU="$(getconf _NPROCESSORS_ONLN)" \
&& DEB_HOST_MULTIARCH="$(dpkg-architecture -q DEB_HOST_MULTIARCH)" \
&& CC_OPT="$(DEB_BUILD_MAINT_OPTIONS="hardening=+all,-pie" DEB_CFLAGS_MAINT_APPEND="-Wp,-D_FORTIFY_SOURCE=2 -fPIC" dpkg-buildflags --get CFLAGS)" \
&& LD_OPT="$(DEB_BUILD_MAINT_OPTIONS="hardening=+all,-pie" DEB_LDFLAGS_MAINT_APPEND="-Wl,--as-needed -pie" dpkg-buildflags --get LDFLAGS)" \
&& CONFIGURE_ARGS="--prefix=/usr \
--state=/var/lib/unit \
--control=unix:/var/run/control.unit.sock \
--pid=/var/run/unit.pid \
--log=/var/log/unit.log \
--tmp=/var/tmp \
--user=unit \
--group=unit \
--openssl \
--libdir=/usr/lib/$DEB_HOST_MULTIARCH" \
&& ./configure $CONFIGURE_ARGS --cc-opt="$CC_OPT" --ld-opt="$LD_OPT" --modules=/usr/lib/unit/debug-modules --debug \
&& make -j $NCPU unitd \
&& install -pm755 build/unitd /usr/sbin/unitd-debug \
&& make clean \
&& ./configure $CONFIGURE_ARGS --cc-opt="$CC_OPT" --ld-opt="$LD_OPT" --modules=/usr/lib/unit/modules \
&& make -j $NCPU unitd \
&& install -pm755 build/unitd /usr/sbin/unitd \
&& make clean \
&& ./configure $CONFIGURE_ARGS --cc-opt="$CC_OPT" --modules=/usr/lib/unit/debug-modules --debug \
&& ./configure nodejs --node-gyp=/usr/local/lib/node_modules/npm/bin/node-gyp-bin/node-gyp \
&& make -j $NCPU node node-install libunit-install \
&& make clean \
&& ./configure $CONFIGURE_ARGS --cc-opt="$CC_OPT" --modules=/usr/lib/unit/modules \
&& ./configure nodejs --node-gyp=/usr/local/lib/node_modules/npm/bin/node-gyp-bin/node-gyp \
&& make -j $NCPU node node-install libunit-install \
&& ldd /usr/sbin/unitd | awk '/=>/{print $(NF-1)}' | while read n; do dpkg-query -S $n; done | sed 's/^\([^:]\+\):.*$/\1/' | sort | uniq > /requirements.apt
FROM node:16 as PRODUCTION
COPY docker-entrypoint.sh /usr/local/bin/
COPY --from=BUILDER /usr/sbin/unitd /usr/sbin/unitd
COPY --from=BUILDER /usr/sbin/unitd-debug /usr/sbin/unitd-debug
COPY --from=BUILDER /usr/lib/unit/ /usr/lib/unit/
COPY --from=BUILDER /requirements.apt /requirements.apt
COPY --from=BUILDER /usr/lib/*-linux-gnu/libunit.a /tmp/
COPY --from=BUILDER /usr/include/nxt_* /usr/include/
COPY --from=BUILDER /usr/local/lib/node_modules/unit-http/ /usr/local/lib/node_modules/unit-http/
USER root
RUN set -x \
&& if [ -f "/tmp/libunit.a" ]; then \
mv /tmp/libunit.a /usr/lib/$(dpkg-architecture -q DEB_HOST_MULTIARCH)/libunit.a; \
rm -f /tmp/libunit.a; \
fi \
&& mkdir -p /var/lib/unit/ \
&& mkdir /docker-entrypoint.d/ \
&& addgroup --system unit \
&& adduser \
--system \
--disabled-login \
--ingroup unit \
--no-create-home \
--home /nonexistent \
--gecos "unit user" \
--shell /bin/false \
unit \
&& apt update \
&& apt --no-install-recommends --no-install-suggests -y install curl $(cat /requirements.apt) \
&& apt-get clean && rm -rf /var/lib/apt/lists/* \
&& rm -f /requirements.apt \
&& ln -sf /dev/stdout /var/log/unit.log
STOPSIGNAL SIGTERM
ENTRYPOINT ["bash", "/usr/local/bin/docker-entrypoint.sh"]
CMD ["sudo", "unitd", "--no-daemon", "--control", "unix:/var/run/control.unit.sock"]
#FROM nginx/unit:1.27.0-node16
EXPOSE 8080
WORKDIR /usr/app
# Copy in build artifacts, build project dependencies
COPY src/frontend/dpia-webapp/package*.json ./
RUN npm install -g sass
RUN npm install
RUN apt-get update && apt install make
COPY src/frontend/dpia-webapp/. .
RUN make compile
COPY src/frontend/dpia-webapp/unitd-conf.json /docker-entrypoint.d/
#RUN unitd --control 127.0.0.1:8224
CMD ["unitd", "--no-daemon", "--control", "unix:/var/run/control.unit.sock", "--log", "/usr/app/unit.log"]
I am not sure why is NGINX Unit running in unprivileged mode? Is there a way to make it run priviliged
I believe it is failing at this line: CMD ["sudo", "unitd", "--no-daemon", "--control", "unix:/var/run/control.unit.sock"]
This docker file script is taken directly from NGINX UNIT docker script: https://github.com/nginx/unit/blob/master/pkg/docker/Dockerfile.node16
You have a commented FROM line which therefor never executes:
#FROM nginx/unit:1.27.0-node16
as a consequence, everything that follows is part of the same stage. And because of this your last CMD line:
CMD ["unitd", "--no-daemon", "--control", "unix:/var/run/control.unit.sock", "--log", "/usr/app/unit.log"]
will overwrite the previous one:
CMD ["sudo", "unitd", "--no-daemon", "--control", "unix:/var/run/control.unit.sock"]
So the one with sudo is actually never executed.
If you fix this situation somehow, I think it will work. Either add sudo to the last CMD or just delete it.

Docker failed to bind to $PORT within 60 seconds of launch – HEROKU ERROR

I am trying to deploy a Dockerfile from dockerhub on heroku using github workflow but I am getting error Failed to bind to $PORT within 60 seconds of launch – HEROKU ERROR.
Below is my Dockerfile.
FROM ghcr.io/linuxserver/baseimage-alpine:3.15
WORKDIR /app
# set version label
ARG UNRAR_VERSION=6.1.4
ARG BUILD_DATE
ARG VERSION
ARG SABNZBD_VERSION
LABEL build_version="Linuxserver.io version:- ${VERSION} Build-date:- ${BUILD_DATE}"
LABEL maintainer="thespad"
# environment settings
ENV HOME="/config" \
PORT=8080 \
PYTHONIOENCODING=utf-8
RUN \
echo "**** install packages ****" && \
apk add -U --update --no-cache --virtual=build-dependencies \
build-base \
g++ \
gcc \
libffi-dev \
make \
openssl-dev \
python3-dev && \
apk add -U --update --no-cache \
curl \
p7zip \
par2cmdline \
python3 \
py3-pip && \
echo "**** install unrar from source ****" && \
mkdir /tmp/unrar && \
curl -o \
/tmp/unrar.tar.gz -L \
"https://www.rarlab.com/rar/unrarsrc-${UNRAR_VERSION}.tar.gz" && \
tar xf \
/tmp/unrar.tar.gz -C \
/tmp/unrar --strip-components=1 && \
cd /tmp/unrar && \
make && \
install -v -m755 unrar /usr/local/bin && \
echo "**** install sabnzbd ****" && \
if [ -z ${SABNZBD_VERSION+x} ]; then \
SABNZBD_VERSION=$(curl -s https://api.github.com/repos/sabnzbd/sabnzbd/releases/latest \
| awk '/tag_name/{print $4;exit}' FS='[""]'); \
fi && \
mkdir -p /app/sabnzbd && \
curl -o \
/tmp/sabnzbd.tar.gz -L \
"https://github.com/sabnzbd/sabnzbd/releases/download/${SABNZBD_VERSION}/SABnzbd-${SABNZBD_VERSION}-src.tar.gz" && \
tar xf \
/tmp/sabnzbd.tar.gz -C \
/app/sabnzbd --strip-components=1 && \
cd /app/sabnzbd && \
python3 -m pip install --upgrade pip && \
pip3 install -U --no-cache-dir --find-links https://wheel-index.linuxserver.io/alpine-3.15/ \
wheel \
apprise \
pynzb \
requests && \
pip3 install -U --no-cache-dir --find-links https://wheel-index.linuxserver.io/alpine-3.15/ -r requirements.txt && \
echo "**** install nzb-notify ****" && \
NZBNOTIFY_VERSION=$(curl -s https://api.github.com/repos/caronc/nzb-notify/releases/latest \
| awk '/tag_name/{print $4;exit}' FS='[""]') && \
mkdir -p /app/nzbnotify && \
curl -o \
/tmp/nzbnotify.tar.gz -L \
"https://api.github.com/repos/caronc/nzb-notify/tarball/${NZBNOTIFY_VERSION}" && \
tar xf \
/tmp/nzbnotify.tar.gz -C \
/app/nzbnotify --strip-components=1 && \
cd /app/nzbnotify && \
pip3 install -U --no-cache-dir --find-links https://wheel-index.linuxserver.io/alpine-3.15/ -r requirements.txt && \
echo "**** cleanup ****" && \
ln -s \
/usr/bin/python3 \
/usr/bin/python && \
apk del --purge \
build-dependencies && \
rm -rf \
/tmp/* \
$HOME/.cache
# add local files
COPY ./config /config
# ports and volumes
EXPOSE $PORT
# ENV LISTEN_PORT 8080
# PORT=8080
VOLUME /config
CMD exec /app/sabnzbd/Sabnzbd --NoRestart --NoUpdates -p $PORT
I don't know why heroku showing Port error even though I have exposed the port.
Can Anyone please help me with the error. I want to deploy Sabnzbd on heroku using Docker.

How to correct provide web pack for my symfony project in docker?

I have app with Symfony5 and I need to applu web pack to my app. For that I enter in php-fpm container and follow instruction:
composer require symfony/webpack-encore-bundle
yarn install
yarn: not found
how to correct provide web pack for my app ?
docker compose:
php:
container_name: php-fpm
build: ./php-fpm
ports:
- "9000:9001"
environment: # You can use this section to set environment variables. But you can also use the .env file.
- MESSENGER_TRANSPORT_DSN=${MESSENGER_TRANSPORT_DSN} # AMQP connection string-
volumes:
- ./symfony:/var/www/symfony:cached
- ./logs/symfony:/var/www/symfony/var/log:cached
links:
- redis
depends_on:
- db
networks:
- php
Dockerfile
FROM alpine:3.10
LABEL maintainer="Vincent Composieux <vincent.composieux#gmail.com>"
RUN apk add --update --no-cache \
coreutils \
php7-fpm \
php7-apcu \
php7-ctype \
php7-curl \
php7-dom \
php7-gd \
php7-iconv \
php7-imagick \
php7-json \
php7-intl \
php7-mcrypt \
php7-fileinfo\
php7-mbstring \
php7-opcache \
php7-openssl \
php7-pdo \
php7-pdo_mysql \
php7-mysqli \
php7-pdo_pgsql \
php7-pgsql \
php7-xml \
php7-zlib \
php7-phar \
php7-tokenizer \
php7-session \
php7-simplexml \
php7-xdebug \
php7-zip \
php7-xmlwriter \
make \
curl \
zlib-dev \
libxml2-dev \
rabbitmq-c-dev \
oniguruma-dev \
php7-pecl-amqp \
php7-amqp \
php7-redis
RUN echo "$(curl -sS https://composer.github.io/installer.sig) -" > composer-setup.php.sig \
&& curl -sS https://getcomposer.org/installer | tee composer-setup.php | sha384sum -c composer-setup.php.sig \
&& php composer-setup.php && rm composer-setup.php* \
&& chmod +x composer.phar && mv composer.phar /usr/bin/composer
COPY symfony.ini /etc/php7/conf.d/
COPY symfony.ini /etc/php7/cli/conf.d/
COPY xdebug.ini /etc/php7/conf.d/
COPY symfony.pool.conf /etc/php7/php-fpm.d/
CMD ["php-fpm7", "-F"]
WORKDIR /var/www/symfony
EXPOSE 9001
You need to install yarn, replace the following in your Dockerfile:
RUN apk add --update --no-cache \
coreutils \
...
with
RUN apk add --update --no-cache \
coreutils \
yarn \
...

Docker multi-stage build not copying between stages

I'm trying to create a multi-stage build where the first stage does a yarn install for the theme and the second stage sets up the PHP environment for Drupal.
When I look at the output it looks like yarn install is being run but the COPY command near the bottom doesn't copy it across to the PHP image. If I'm right when this works the node_modules directory should be created on my local machine?
docker-compose.yml:
version: '3.7'
services:
web:
build:
context: .
dockerfile: Dockerfile
volumes:
- ./:/var/www/html:cached
env_file:
- ./local-development.env
ports:
- "8888:80"
db:
image: mysql:5.7
env_file:
- ./local-development.env
ports:
- "3306:3306"
Dockerfile:
FROM node:latest as yarn-install
WORKDIR /app
COPY ./web/themes/material_admin_mine ./
RUN yarn install --verbose --force;
# from https://www.drupal.org/docs/8/system-requirements/drupal-8-php-requirements
FROM php:7.2-apache
# Install & setup Xdebug
RUN yes | pecl install xdebug \
&& echo "zend_extension=$(find /usr/local/lib/php/extensions/ -name xdebug.so)" > /usr/local/etc/php/conf.d/xdebug.ini \
&& echo "xdebug.remote_enable=1" >> /usr/local/etc/php/conf.d/xdebug.ini \
&& echo 'xdebug.remote_connect_back=0' >> /usr/local/etc/php/conf.d/xdebug.ini \
&& echo 'xdebug.remote_host=docker.for.mac.localhost' >> /usr/local/etc/php/conf.d/xdebug.ini \
&& echo 'xdebug.remote_port=9000' >> /usr/local/etc/php/conf.d/xdebug.ini \
&& echo 'xdebug.remote_handler=dbgp' >> /usr/local/etc/php/conf.d/xdebug.ini \
&& echo 'xdebug.remote_mode=req' >> /usr/local/etc/php/conf.d/xdebug.ini \
&& echo 'xdebug.remote_autostart=1' >> /usr/local/etc/php/conf.d/xdebug.ini \
&& echo 'xdebug.idekey=PHPSTORM' >> /usr/local/etc/php/conf.d/xdebug.ini
# Install git & mysql-client for running Drush
RUN apt update; \
apt install -y \
git \
mysql-client
# install the PHP extensions we need
RUN set -ex; \
\
if command -v a2enmod; then \
a2enmod rewrite; \
fi; \
\
savedAptMark="$(apt-mark showmanual)"; \
\
apt-get update; \
apt-get install -y --no-install-recommends \
libjpeg-dev \
libpng-dev \
libpq-dev \
unzip \
git \
; \
\
curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer; \
\
docker-php-ext-configure gd --with-png-dir=/usr --with-jpeg-dir=/usr; \
docker-php-ext-install -j "$(nproc)" \
gd \
opcache \
pdo_mysql \
pdo_pgsql \
zip \
; \
\
# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
apt-mark auto '.*' > /dev/null; \
apt-mark manual $savedAptMark; \
ldd "$(php -r 'echo ini_get("extension_dir");')"/*.so \
| awk '/=>/ { print $3 }' \
| sort -u \
| xargs -r dpkg-query -S \
| cut -d: -f1 \
| sort -u \
| xargs -rt apt-mark manual; \
\
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
rm -rf /var/lib/apt/lists/*
# set recommended PHP.ini settings
# see https://secure.php.net/manual/en/opcache.installation.php
RUN { \
echo 'opcache.memory_consumption=128'; \
echo 'opcache.interned_strings_buffer=8'; \
echo 'opcache.max_accelerated_files=4000'; \
echo 'opcache.revalidate_freq=60'; \
echo 'opcache.fast_shutdown=1'; \
echo 'opcache.enable_cli=1'; \
} > /usr/local/etc/php/conf.d/opcache-recommended.ini
# Various packages required to run Gulp in the theme directory
# gnupg is require for nodejs
RUN apt update; \
apt install gnupg -y; \
apt install gnupg1 -y; \
apt install gnupg2 -y; \
cd ~; \
curl -sL https://deb.nodesource.com/setup_10.x -o nodesource_setup.sh; \
bash nodesource_setup.sh; \
apt install nodejs -y; \
npm install gulp-cli -g -y; \
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - ;\
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list; \
apt update && apt install yarn -y;
WORKDIR /var/www/html
COPY --from=0 /app ./web/themes/material_admin_mine
When your Dockerfile ends with:
WORKDIR /var/www/html
COPY --from=0 /app ./web/themes/material_admin_mine
That should in fact copy the data from the first build stage to the final image. But then when you launch the container with
volumes:
- ./:/var/www/html:cached
everything in the /var/www/html directory tree, including that final COPY step, is hidden and replaced with what's in the current directory on the host. If you think of this like a copy, it's a one-way copy into the container; later changes will get copied back out to the host, but there's nothing that synchronizes what's in the image with what you previously had in the directory at startup time.
A Dockerfile intrinsically can't affect host filesystem content. In your case it sounds like the host content is secondary to your application proper. Given what's going into the first stage, I'd just run the yarn install step on the host and be done with it (you probably already have Node and Yarn available even). Otherwise you'd need a more selective volumes: section that carefully tried to avoid overwriting that one directory; you might be able to mount something like ./web/src:/var/www/html/web/src to only include your application code and avoid hiding the .../web/themes tree.

Docker image Size increases if I remove few lines of code

I'm trying to reduce the docker image size, but Dockerfile is being weird.
I concatenate the RUN command to reduce the size of the image. When I build the below Dockerfile it creates only 235MB.
FROM nginx:alpine
RUN apk add --no-cache --virtual .build-deps \
gcc \
libc-dev \
make \
openssl \
pcre-dev \
zlib-dev \
linux-headers \
curl \
gnupg \
libxslt-dev \
gd-dev \
perl-dev \
&& apk add --no-cache --virtual .libmodsecurity-deps \
pcre-dev \
libxml2-dev \
git \
libtool \
automake \
autoconf \
g++ \
flex \
bison \
yajl-dev \
git \
# Add runtime dependencies that should not be removed
&& apk add --no-cache \
doxygen \
geoip \
geoip-dev \
yajl \
libstdc++ \
sed \
# Installing ModSec Library version 3
&& echo "Installing ModSec Library" \
&& git clone -b v3/master --single-branch https://github.com/SpiderLabs/ModSecurity /opt/ModSecurity \
&& cd /opt/ModSecurity \
&& git submodule init \
&& git submodule update \
&& ./build.sh \
&& ./configure && make && make install \
&& echo "Finished Installing ModSec Library" \
# Installing ModSec - Nginx connector
&& cd /opt \
&& echo 'Installing ModSec - Nginx connector' \
&& git clone --depth 1 https://github.com/SpiderLabs/ModSecurity-nginx.git \
&& wget http://nginx.org/download/nginx-$NGINX_VERSION.tar.gz \
&& tar zxvf nginx-$NGINX_VERSION.tar.gz \
# Adding Nginx Connector Module
&& cd /opt/nginx-$NGINX_VERSION \
&& ./configure --with-compat --add-dynamic-module=../ModSecurity-nginx \
&& make modules \
&& cp objs/ngx_http_modsecurity_module.so /etc/nginx/modules \
&& echo "Finished Installing ModSec - Nginx connector" \
# Begin installing ModSec OWASP Rules
&& echo "Begin installing ModSec OWASP Rules" \
&& mkdir /etc/nginx/modsec \
&& wget -P /etc/nginx/modsec/ https://raw.githubusercontent.com/SpiderLabs/ModSecurity/v3/master/modsecurity.conf-recommended \
&& mv /etc/nginx/modsec/modsecurity.conf-recommended /etc/nginx/modsec/modsecurity.conf \
&& sed -i 's/SecRuleEngine DetectionOnly/SecRuleEngine On/' /etc/nginx/modsec/modsecurity.conf \
# Fetching owasp-modsecurity-crs
&& cd /opt \
&& git clone -b v3.0/master https://github.com/SpiderLabs/owasp-modsecurity-crs \
&& mv owasp-modsecurity-crs/ /usr/local/ \
&& cp /usr/local/owasp-modsecurity-crs/crs-setup.conf.example /usr/local/owasp-modsecurity-crs/crs-setup.conf \
# Creating modsec file
&& echo 'Creating modsec file' \
&& echo -e '# From https://github.com/SpiderLabs/ModSecurity/blob/master/\n \
# modsecurity.conf-recommended\n \
# Edit to set SecRuleEngine On\n \
Include "/etc/nginx/modsec/modsecurity.conf"\n \
# OWASP CRS v3 rules\n \
Include "/usr/local/owasp-modsecurity-crs/crs-setup.conf"\n \
Include "/usr/local/owasp-modsecurity-crs/rules/*.conf"'\
>>/etc/nginx/modsec/main.conf \
&& chown nginx:nginx /etc/nginx/modsec/main.conf \
# Removing old Nginx conf files
&& rm -fr /etc/nginx/conf.d/ \
&& rm -fr /etc/nginx/nginx.conf \
&& chown -R nginx:nginx /usr/share/nginx \
# delete uneeded and clean up
&& apk del .build-deps \
&& apk del .libmodsecurity-deps \
&& rm -fr ModSecurity \
&& rm -fr ModSecurity-nginx \
&& rm -fr nginx-$NGINX_VERSION.tar.gz \
&& rm -fr nginx-$NGINX_VERSION
COPY conf/nginx.conf /etc/nginx
COPY conf/conf.d /etc/nginx/conf.d
COPY errors /usr/share/nginx/errors
WORKDIR /usr/share/nginx/html
CMD nginx -g 'daemon off;'
EXPOSE 80
I have seen the docker history imagedId it shows that this RUN command has an increased size around 855MB. Anybody Understand why it is behaving weird?
Any thoughts would be much helpful, its is hard to debug building the image everytime.
I tried building in both ways and found not much difference.
Most of the disk space is consumed by /opt/ModSecurity
Initially it was 74MB after git clone.
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
oldimage latest 924a8d4f941e 11 minutes ago 867MB
newimage latest d1ca029927c2 About an hour ago 867MB
nginx alpine ebe2c7c61055 6 days ago 18MB
However after building the complete build - it has grown to ~650MB.
$ du -sh *
639.7M ModSecurity
408.0K ModSecurity-nginx
7.5M nginx-1.13.12
996.0K nginx-1.13.12.tar.gz

Resources