How to create generic docker images without specific parameters - azure

I use a workflow engine called Camunda with a docker image, this tool connects to an Azure SQL instance and I created the image with the code below (removed some info for security purposes).
Then I pushed the image to Azure Container Registry and it works perfect for our DEV environment.
However I would like to use the same image for our Staging and Production Environment.
How can I remove the connection string settins from the docker file with variables and then replace those variables at deployment time?
FROM alpine:3.10 as builder
ARG VERSION=7.12.0
ARG DISTRO=tomcat
ARG SNAPSHOT=true
ARG EE=false
ARG USER
ARG PASSWORD
RUN apk add --no-cache \
ca-certificates \
maven \
tar \
wget \
xmlstarlet
COPY settings.xml download.sh camunda-tomcat.sh camunda-wildfly.sh /tmp/
RUN /tmp/download.sh
#Enable Basic AUTH
COPY web.xml /camunda/webapps/engine-rest/WEB-INF/web.xml
##### FINAL IMAGE #####
FROM alpine:3.10
ARG VERSION=7.12.0
ENV CAMUNDA_VERSION=${VERSION}
ENV DB_DRIVER=com.microsoft.sqlserver.jdbc.SQLServerDriver
ENV DB_URL=jdbc:sqlserver://servername.database.windows.net:1433;database=abc;user=username#servername;password={bcd};encrypt=true;trustServerCertificate=false;hostNameInCertificate=*.database.windows.net;loginTimeout=30;
ENV DB_USERNAME=username#servername
ENV DB_PASSWORD=bcd
ENV DB_CONN_MAXACTIVE=20
ENV DB_CONN_MINIDLE=5
ENV DB_CONN_MAXIDLE=20
ENV DB_VALIDATE_ON_BORROW=true
ENV DB_VALIDATION_QUERY="SELECT 1"
ENV SKIP_DB_CONFIG=
ENV WAIT_FOR=
ENV WAIT_FOR_TIMEOUT=120
ENV TZ=UTC
ENV DEBUG=TRUE
ENV JAVA_OPTS="-Xmx768m -XX:MaxMetaspaceSize=256m"
EXPOSE 8080 8000
# Downgrading wait-for-it is necessary until this PR is merged
# https://github.com/vishnubob/wait-for-it/pull/68
RUN apk add --no-cache \
bash \
ca-certificates \
openjdk11-jre-headless \
tzdata \
tini \
xmlstarlet \
&& wget -O /usr/local/bin/wait-for-it.sh \
"https://raw.githubusercontent.com/vishnubob/wait-for-it/a454892f3c2ebbc22bd15e446415b8fcb7c1cfa4/wait-for-it.sh" --no-check-certificate \
&& chmod +x /usr/local/bin/wait-for-it.sh
RUN addgroup -g 1000 -S camunda && \
adduser -u 1000 -S camunda -G camunda -h /camunda -s /bin/bash -D camunda
WORKDIR /camunda
USER camunda
#MSSQL SERVER JDBC DRIVER INSTALL
COPY mssql-jdbc-7.2.2.jre11.jar /camunda/lib/
ENTRYPOINT ["/sbin/tini", "--"]
CMD ["./camunda.sh"]
COPY --chown=camunda:camunda --from=builder /camunda .

Related

How to avoid changing permissions on node_modules for a non-root user in docker

The issue with my current files is that in my entrypoint.sh file, I have to change the ownership of my entire project directory to the non-administrative user (chown -R node /node-servers). However, when a lot of npm packages are installed, this takes a lot of time. Is there a way to avoid having to chown the node_modules directory?
Background: The reason I create everything as root in the Dockerfile is because this way I can match the UID and GID of a developer's local user. This enables mounting volumes more easily. The downside is that I have to step-down from root in an entrypoint.sh file and ensure that the permissions of the entire project files have all been changed to the non-administrative user.
my docker file:
FROM node:10.24-alpine
#image already has user node and group node which are 1000, thats what we will use
# grab gosu for easy step-down from root
# https://github.com/tianon/gosu/releases
ENV GOSU_VERSION 1.14
RUN set -eux; \
\
apk add --no-cache --virtual .gosu-deps \
ca-certificates \
dpkg \
gnupg \
; \
\
dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \
wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \
wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \
\
# verify the signature
export GNUPGHOME="$(mktemp -d)"; \
gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \
gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \
command -v gpgconf && gpgconf --kill all || :; \
rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; \
\
# clean up fetch dependencies
apk del --no-network .gosu-deps; \
\
chmod +x /usr/local/bin/gosu; \
# verify that the binary works
gosu --version; \
gosu nobody true
COPY ./ /node-servers
# Setting the working directory
WORKDIR /node-servers
# Install app dependencies
# Install openssl
RUN apk add --update openssl ca-certificates && \
apk --no-cache add shadow && \
apk add libcap && \
npm install -g && \
chmod +x /node-servers/entrypoint.sh && \
setcap cap_net_bind_service=+ep /usr/local/bin/node
# Entrypoint used to load the environment and start the node server
#ENTRYPOINT ["/bin/sh"]
my entrypoint.sh
# In Prod, this may be configured with a GID already matching the container
# allowing the container to be run directly as Jenkins. In Dev, or on unknown
# environments, run the container as root to automatically correct docker
# group in container to match the docker.sock GID mounted from the host
set -x
if [ -z ${HOST_UID+x} ]; then
echo "HOST_UID not set, so we are not changing it"
else
echo "HOST_UID is set, so we are changing the container UID to match"
# get group of notadmin inside container
usermod -u ${HOST_UID} node
CUR_GID=`getent group node | cut -f3 -d: || true`
echo ${CUR_GID}
# if they don't match, adjust
if [ ! -z "$HOST_GID" -a "$HOST_GID" != "$CUR_GID" ]; then
groupmod -g ${HOST_GID} -o node
fi
if ! groups node | grep -q node; then
usermod -aG node node
fi
fi
# gosu drops from root to node user
set -- gosu node "$#"
[ -d "/node-servers" ] && chown -v -R node /node-servers
exec "$#"
You shouldn't need to run chown at all here. Leave the files owned by root (or by the host user). So long as they're world-readable the application will still be able to run; but if there's some sort of security issue or other bug, the application won't be able to accidentally overwrite its own source code.
You can then go on to simplify this even further. For most purposes, users in Unix are identified by their numeric user ID; there isn't actually a requirement that the user be listed in /etc/passwd. If you don't need to change the node user ID and you don't need to chown files, then the entrypoint script reduces to "switch user IDs and run the main script"; but then Docker can provide an alternate user ID for you via the docker run -u option. That means you don't need to install gosu either, which is a lot of the Dockerfile content.
All of this means you can reduce the Dockerfile to:
FROM node:10.24-alpine
# Install OS-level dependencies (before you COPY anything in)
apk add openssl ca-certificates
# (Do not install gosu or its various dependencies)
# Set (and create) the working directory
WORKDIR /node-servers
# Copy language-level dependencies in
COPY package.json package-lock.json .
RUN npm ci
# Copy the rest of the application in
# (make sure `node_modules` is in .dockerignore)
COPY . .
# (Do not call setcap here)
# Set the main command to run
USER node
CMD npm run start
Then when you run the container, you can use Docker options to specify the current user and additional capability.
docker run \
-d \ # in the background
-u $(id -u) \ # as an alternate user
-v "$PWD/data:/node-servers/data" \ # mounting a data directory
-p 8080:80 \ # publishing a port
my-image
Docker grants the NET_BIND_SERVICE capability by default so you don't need to specially set it.
This same permission setup will work if you're using bind mounts to overwrite the application code; again, without a chown call.
docker run ... \
-u $(id -u) \
-v "$PWD:/node-servers" \ # run the application from the host, not the image
-v /node-servers/node_modules \ # with libraries that will not be updated ever
...

Can't install LiipImagineBundle 2.3 on Symfony 4.4 with Docker in prod environment

In my Dockerized Symfony 4.4 project I can switch between dev and prod environments with two commands : make up-dev and make up-prod (using Makefile)
In dev mode, inside the container, I can install LiipImagineBundle with no problem, then when I switch to prod environment the make up-prod exits with this error message :
Generated optimized autoload files containing 7171 classes
+ APP_ENV=prod composer run-script --no-dev post-install-cmd
Run composer recipes at any time to see the status of your Symfony recipes.
Executing script cache:clear [KO]
[KO]
Script cache:clear returned with error code 1
!!
!! // Clearing the cache for the prod environment with debug
!! // false
!!
!!
!! In EnvVarProcessor.php line 171:
!!
!! Environment variable not found: "APP_SECRET".
!!
!!
!! cache:clear [--no-warmup] [--no-optional-warmers] [-h|--help] [-q|--quiet] [-v|vv|vvv|--verbose] [-V|--version] [--ansi] [--no-ansi] [-n|--no-interaction] [-e|--env ENV] [--no-debug] [--] <command>
!!
!!
Script #auto-scripts was called via post-install-cmd
ERROR: Service 'app' failed to build: The command '/bin/sh -c set -eux; mkdir -p var/cache var/log; chmod +x bin/console; composer dump-autoload --no-dev --no-scripts --optimize; APP_ENV=prod composer run-script --no-dev post-install-cmd' returned a non-zero code: 1
make: *** [Makefile:26: up] Error 1
This is my Dockerfile :
##
# Base
##
FROM debian:9-slim as base
ENV TERM="xterm" \
DEBIAN_FRONTEND="noninteractive" \
TIMEZONE="Europe/Paris" \
COMPOSER_ALLOW_SUPERUSER=1 \
NODE_VERSION=8.12.0 \
PHP_VERSION=7.2
# System depdendencies
RUN apt-get update --quiet && \
apt-get install --quiet --no-install-recommends --yes \
apt-transport-https \
ca-certificates \
lsb-release \
wget && \
wget -O /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg && \
echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" >> /etc/apt/sources.list.d/php.list && \
apt-get update --quiet && \
apt-get install --quiet --no-install-recommends --yes \
curl \
git \
nginx \
php${PHP_VERSION} \
php${PHP_VERSION}-apcu \
php${PHP_VERSION}-curl \
php${PHP_VERSION}-dom \
php${PHP_VERSION}-fpm \
php${PHP_VERSION}-gd \
php${PHP_VERSION}-iconv \
php${PHP_VERSION}-intl \
php${PHP_VERSION}-mbstring \
php${PHP_VERSION}-mysql \
php${PHP_VERSION}-opcache \
php${PHP_VERSION}-pdo \
php${PHP_VERSION}-uuid \
php${PHP_VERSION}-xml \
php${PHP_VERSION}-simplexml \
php${PHP_VERSION}-zip \
supervisor \
p7zip-full \
tzdata \
unzip \
libxml2-dev \
php${PHP_VERSION}-soap \
vim && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* && \
mkdir /run/php && \
cp /usr/share/zoneinfo/${TIMEZONE} /etc/localtime && \
echo "${TIMEZONE}" > /etc/timezone
# Composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer && \
composer global require "hirak/prestissimo:^0.3" --prefer-dist --no-progress --no-suggest --classmap-authoritative && \
composer clear-cache
# Yarn
RUN curl -L -o /tmp/nodejs.tar.gz https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-x64.tar.gz && \
tar xfvz /tmp/nodejs.tar.gz -C /usr/local --strip-components=1 && \
rm -f /tmp/nodejs.tar.gz && \
npm install yarn -g
COPY .docker/php.ini /etc/php/${PHP_VERSION}/cli/conf.d/50-setting.ini
COPY .docker/php.ini /etc/php/${PHP_VERSION}/fpm/conf.d/50-setting.ini
COPY .docker/pool.conf /etc/php/${PHP_VERSION}/fpm/pool.d/www.conf
COPY .docker/nginx.conf /etc/nginx/nginx.conf
COPY .docker/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
EXPOSE 80
CMD ["supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]
WORKDIR /app
##
# Production
##
FROM base as prod
# PHP dependencies
COPY composer.json composer.lock symfony.lock ./
RUN set -eux; \
composer install --no-dev --no-autoloader --no-scripts --no-progress --no-suggest
COPY bin bin/
COPY config config/
COPY public public/
COPY src src/
COPY templates templates/
COPY translations translations/
COPY resources resources/
RUN set -eux; \
mkdir -p var/cache var/log; \
chmod +x bin/console; \
composer dump-autoload --no-dev --no-scripts --optimize; \
APP_ENV=prod composer run-script --no-dev post-install-cmd
# Assets dependencies
COPY assets/ ./assets
COPY package.json yarn.lock webpack.config.js ./
RUN set -eux; \
mkdir -p public/build; \
yarn install --no-progress; \
yarn encore production
RUN usermod -u 1000 www-data
And this is the Makefile :
EXEC := docker-compose exec app
PHP := $(EXEC) php -d memory_limit=-1
CONSOLE := $(PHP) bin/console
##
# Service
##
.PHONY: up-dev up-prod up down
up-dev: export ENV := dev
up-dev: up vendor public/build
$(CONSOLE) cache:clear
ifeq ($(shell uname), Linux)
$(EXEC) chown -R $(shell id -u):$(shell id -g) .
endif
up-prod: export ENV := prod
up-prod: up
up-beta: export ENV := beta
up-beta: up
up:
docker-compose -f docker-compose.yml -f docker-compose.$(ENV).yml up -d --build --remove-orphans
I think FROM base as prod is the source of the problem but can't figure out how to fix it and don't want to modify this section since I took the project on the way.
I'm sure LiipImagine is the source of the problem because before installing it make up-prod worked fine !
UPDATE #1
I've tried two updates :
First one : I've deleted this :
RUN set -eux; \
mkdir -p var/cache var/log; \
chmod +x bin/console; \
composer dump-autoload --no-dev --no-scripts --optimize; \
APP_ENV=prod composer run-script --no-dev post-install-cmd
Second one : I've added APP_SECRET like this
RUN set -eux; \
...
APP_ENV=prod APP_SECRET=sameValueAsDotEnv composer run-script --no-dev post-install-cmd
In both cases, the make up-prod works fine with no errors, but I have to run composer install inside the container otherwise depencies are missing ... I really don't get it :(
UPDATE #2
Based on the 1st part of Update #1, I've added this to the up section of Makefile :
$(EXEC) composer install --no-interaction
Now make up-prod is ok, but I still can't find the root of the problem !
I see the error:
Environment variable not found: "APP_SECRET".
First of all, check your .env and .env.loc files include this variable. I guess, that in DEV mode APP_SECRET is set up randomly, but it must be specified explicitly in the PROD.
Secondly, pay attention that DEV and PROD install dependencies slightly different:
if [ "$APP_ENV" = 'prod' ]; then
composer install --prefer-dist --no-dev --no-progress --no-suggest --optimize-autoloader --classmap-authoritative --no-interaction
else
composer install --prefer-dist --no-progress --no-suggest --no-interaction
fi
Hope, it will give you the right direction.
Well it works after I've added APP_SECRET like this
RUN set -eux; \
...
APP_ENV=prod APP_SECRET=123 composer run-script --no-dev post-install-cmd
Inside the container the APP_SECRET env variable contains the value defined in .env file not 123 ! I really don't understand why I have to add APP_SECRET before composer !

How to add SSH access to a docker container

I have the following DOCKER FILE
FROM alpine:3.10 as builder
ARG VERSION=7.12.0
ARG DISTRO=tomcat
ARG SNAPSHOT=true
ARG EE=false
ARG USER
ARG PASSWORD
RUN apk add --no-cache \
ca-certificates \
maven \
tar \
wget \
xmlstarlet
COPY settings.xml download.sh camunda-tomcat.sh camunda-wildfly.sh /tmp/
RUN /tmp/download.sh
#Enable Basic AUTH
COPY web.xml /camunda/webapps/engine-rest/WEB-INF/web.xml
##### FINAL IMAGE #####
FROM alpine:3.10
ARG VERSION=7.12.0
ENV CAMUNDA_VERSION=${VERSION}
ENV DB_DRIVER=com.microsoft.sqlserver.jdbc.SQLServerDriver
ENV DB_URL=xx
ENV DB_USERNAME=dbname#xx
ENV DB_PASSWORD=xx
ENV DB_CONN_MAXACTIVE=20
ENV DB_CONN_MINIDLE=5
ENV DB_CONN_MAXIDLE=20
ENV DB_VALIDATE_ON_BORROW=true
ENV DB_VALIDATION_QUERY="SELECT 1"
ENV SKIP_DB_CONFIG=
ENV WAIT_FOR=
ENV WAIT_FOR_TIMEOUT=120
ENV TZ=UTC
ENV DEBUG=TRUE
ENV JAVA_OPTS="-Xmx768m -XX:MaxMetaspaceSize=256m"
EXPOSE 8080 8000
# Downgrading wait-for-it is necessary until this PR is merged
# https://github.com/vishnubob/wait-for-it/pull/68
RUN apk add --no-cache \
bash \
ca-certificates \
openjdk11-jre-headless \
tzdata \
tini \
xmlstarlet \
&& wget -O /usr/local/bin/wait-for-it.sh \
"https://raw.githubusercontent.com/vishnubob/wait-for-it/a454892f3c2ebbc22bd15e446415b8fcb7c1cfa4/wait-for-it.sh" --no-check-certificate \
&& chmod +x /usr/local/bin/wait-for-it.sh
RUN addgroup -g 1000 -S camunda && \
adduser -u 1000 -S camunda -G camunda -h /camunda -s /bin/bash -D camunda
WORKDIR /camunda
USER camunda
#MSSQL SERVER JDBC DRIVER INSTALL
COPY mssql-jdbc-7.2.2.jre11.jar /camunda/lib/
ENTRYPOINT ["/sbin/tini", "--"]
CMD ["./camunda.sh"]
COPY --chown=camunda:camunda --from=builder /camunda .
This runs a CAMUNDA workflow Engine with an External SQL Paas Database and it works perfectly fine.
However in order to troubleshoot I need to be able to SSH into the container.
I found on this website how to do it:
https://learn.microsoft.com/en-us/azure/app-service/containers/tutorial-custom-docker-image
However the problem is that both ENTRYPOINT and CMD only allows ONE command, so I am not sure how to start up SSH
# ssh
ENV SSH_PASSWD "root:xyz"
RUN apt-get update \
&& apt-get install -y --no-install-recommends dialog \
&& apt-get update \
&& apt-get install -y --no-install-recommends openssh-server \
&& echo "$SSH_PASSWD" | chpasswd
COPY sshd_config /etc/ssh/
COPY init.sh /usr/local/bin/
RUN chmod u+x /usr/local/bin/init.sh
EXPOSE 8000 2222
# end ssh config
The Azure docs on this could be a bit better but you're almost there.
Firstly, since you're using Alpine Linux, your Dockerfile steps are a bit different from their example. Notably, you use apk add instead of apt-get install. Take a look at this guide which has examples of setting up SSH for Azure with Alpine.
RUN apk add openssh \
&& echo "root:Docker!" | chpasswd
COPY ./path/to/sshd_config /etc/ssh/
The sshd_config should look something like this:
Port 2222
ListenAddress 0.0.0.0
LoginGraceTime 180
X11Forwarding yes
Ciphers aes128-cbc,3des-cbc,aes256-cbc,aes128-ctr,aes192-ctr,aes256-ctr
MACs hmac-sha1,hmac-sha1-96
StrictModes yes
SyslogFacility DAEMON
PasswordAuthentication yes
PermitEmptyPasswords no
PermitRootLogin yes
Subsystem sftp internal-sftp
PidFile /etc/ssh/run/sshd.pid
HostKey /etc/ssh/ssh_host_rsa_key
The last step is to make sure that sshd gets started when the container starts up. While you're right that CMD can only take one command, that command can be a script which runs multiple things. By default, sshd forks a background process rather than running in the foreground so you should be ok. Your startup command could look like this for example:
#!/bin/sh
# ...
# Start sshd for Azure
ssh-keygen -f /etc/ssh/ssh_host_rsa_key -N '' -t rsa
mkdir -p /etc/ssh/run
/usr/sbin/sshd
# Run any additional commands like ./camunda.sh
Azure has some repositories with full sample projects including the SSH setup. Here's a good example although it is Ubuntu and your container is Alpine so it's a bit different.
Here are some suggestions:
create a custom script that you will run at container startup ( CMD tag) that starts the ssh daemon and your other services
(more hacky) like in this answer simply put everything in your CMD

APK Docker Unable to lock database: Permission denied

I have the following errors on docker build
ERROR: Unable to lock database: Permission denied
ERROR: Failed to open apk database: Permission denied
Weird thing is that the first section of APK ADD works fine:
Step 31/41 : RUN apk add --no-cache bash ca-certificates openjdk11-jre-headless tzdata
tini xmlstarlet && wget -O /usr/local/bin/wait-for-it.sh "https://raw.githubusercontent.com/vishnubob/wait-for-it/a454892f3c2ebbc22bd15e446415b8fcb7c1cfa4/wait-for-it.sh" --no-check-certificate && chmod +x /usr/local/bin/wait-for-it.sh
but the second part doesnt:
Step 36/41 : RUN apk add openssh && echo "root:Docker!" | chpasswd
---> Running in 5626e233c96d
ERROR: Unable to lock database: Permission denied
ERROR: Failed to open apk database: Permission denied
my docker file is below
FROM alpine:3.10 as builder
ARG VERSION=7.12.0
ARG DISTRO=tomcat
ARG SNAPSHOT=true
ARG EE=false
ARG USER
ARG PASSWORD
RUN apk add --no-cache \
ca-certificates \
maven \
tar \
wget \
xmlstarlet
COPY settings.xml download.sh camunda-tomcat.sh camunda-wildfly.sh /tmp/
RUN /tmp/download.sh
#Enable Basic AUTH
COPY web.xml /camunda/webapps/engine-rest/WEB-INF/web.xml
##### FINAL IMAGE #####
FROM alpine:3.10
ARG VERSION=7.12.0
ENV CAMUNDA_VERSION=${VERSION}
ENV DB_DRIVER=com.microsoft.sqlserver.jdbc.SQLServerDriver
ENV DB_URL=xxx
ENV DB_USERNAME=xx
ENV DB_PASSWORD=xx
ENV DB_CONN_MAXACTIVE=20
ENV DB_CONN_MINIDLE=5
ENV DB_CONN_MAXIDLE=20
ENV DB_VALIDATE_ON_BORROW=true
ENV DB_VALIDATION_QUERY="SELECT 1"
ENV SKIP_DB_CONFIG=
ENV WAIT_FOR=
ENV WAIT_FOR_TIMEOUT=120
ENV TZ=UTC
ENV DEBUG=TRUE
ENV JAVA_OPTS="-Xmx768m -XX:MaxMetaspaceSize=256m"
EXPOSE 8080 8000
# Downgrading wait-for-it is necessary until this PR is merged
# https://github.com/vishnubob/wait-for-it/pull/68
RUN apk add --no-cache \
bash \
ca-certificates \
openjdk11-jre-headless \
tzdata \
tini \
xmlstarlet \
&& wget -O /usr/local/bin/wait-for-it.sh \
"https://raw.githubusercontent.com/vishnubob/wait-for-it/a454892f3c2ebbc22bd15e446415b8fcb7c1cfa4/wait-for-it.sh" --no-check-certificate \
&& chmod +x /usr/local/bin/wait-for-it.sh
RUN addgroup -g 1000 -S camunda && \
adduser -u 1000 -S camunda -G camunda -h /camunda -s /bin/bash -D camunda
WORKDIR /camunda
USER camunda
#MSSQL SERVER JDBC DRIVER INSTALL
COPY mssql-jdbc-7.2.2.jre11.jar /camunda/lib/
# ssh
RUN apk add openssh \
&& echo "root:Docker!" | chpasswd
COPY sshd_config /etc/ssh/
EXPOSE 80 2222
# end ssh config
ENTRYPOINT ["/sbin/tini", "--"]
CMD "./camunda.sh" && "/usr/sbin/sshd"
COPY --chown=camunda:camunda --from=builder /camunda .
USER camunda
...
RUN apk add openssh
camunda user can't install apk packages, he doesn't have permissions to do so. Install all packages before switching the user. Or switch the user later, just before setting CMD depending on what do you want to do. Or add sudo and add NOPASSWD awk to sudoers file for camunda and do it with sudo. Either way - make sure you have permissions to run apk and following chpassw.

Getting permission denied for /bin/sh to start Go server in production | docker-compose

I'm running sudo docker-compose on my production server to start up my Go container. I have sudo access in my production server but am not the root user.
error:
go_1 | /bin/sh: ./: Permission denied
docker-compose.yml
go:
build:
context: ./api
args:
app_env: ${APP_ENV}
volumes:
- ./api:/go/src/myproject/api
expose:
- "8080"
Go Dockerfile
From golang:1.8.3-alpine3.6
RUN apk update && \
apk add \
bash \
build-base \
curl \
make \
git \
&& rm -rf /var/cache/apk/*
ARG app_env
ENV APP_ENV $app_env
COPY . /go/src/myproject/api
WORKDIR /go/src/myproject/api
CMD if [ ${APP_ENV} = prod ]; \
then \
./; \
else \
go get github.com/pilu/fresh && \
fresh; \
fi
EXPOSE 8080
Any ideas on how to resolve this?
You need to build your go program and then tell Docker, with CMD, to use the resulting binary as the default executable.
Try something like this:
From golang:1.8.3-alpine3.6
RUN apk update && \
apk add \
bash \
build-base \
curl \
make \
git \
&& rm -rf /var/cache/apk/*
ARG app_env
ENV APP_ENV $app_env
COPY . /go/src/myproject/api
WORKDIR /go/src/myproject/api
RUN go get ./
RUN go build
CMD if [ ${APP_ENV} = prod ]; \
then \
api; \
else \
go get github.com/pilu/fresh && \
fresh; \
fi
EXPOSE 8080
If you haven't named the package containing the main function as "main", I found with multi-stage builds it was building but it wasn't a binary.
There was no obvious error message.
Make sure your go code builds and runs on your host, before containerising it.

Resources