We have an angular app we are trying to run in docker nginx.
I have to run a script on startup that uses an environment variableto replace the app url for each stage. This is needed to connect to the backend.
We do not wish to build the container for each stage. The container will run in Azure docker.
For now i am running it locally. It executes my script and then the app shuts down.
The Docker File:
FROM node:8.11.2-alpine as node
LABEL author="My Online Presence"
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
FROM nginx:1.13.12-alpine
COPY /certificates /etc/nginx/
COPY --from=node /usr/src/app/dist /usr/share/nginx/html
COPY ./nginx.conf /etc/nginx/conf.d/default.conf
ADD run.sh /usr/share/nginx/html/run.sh
RUN apk add --update bash && rm -rf /var/cache/apk/*
RUN chmod +x /usr/share/nginx/html/run.sh
ENTRYPOINT ["/usr/share/nginx/html/run.sh"]
CMD ["nginx", "-g", "daemon off;"]
The run.sh file
#!/bin/sh
FILE_NAME=$(find . -name "main*.js")
sed -i "s/localhost\:4200/${DIGITISE_URL}/g" $FILE_NAME
echo 'File updated with correct url'
i use
docker build -t digitise .
and then
docker run -p 80:80 -p 443:443 -e DIGITISE_URL=digitise.co.za digitise
I got it working simply by adding
exec "$#"
to the end of my script being run
You can also start nginx service in your script.
Related
I have the following Dockerfile.PROD, that builds my Nodejs application to then be copied over the Nginx.
I am trying to pass credentials using build arguments to Docker to then use inside a sed command to create a .env file for Nodejs use.
My Dockerfile.PROD
# build environment
FROM node:12.5.0-alpine as build
WORKDIR /app
ENV PATH /app/node_modules/.bin:$PATH
COPY package.json ./
COPY package-lock.json ./
COPY DEFAULT.env ./.env
RUN sed -i "s/access-key/$REACT_APP_ACCESS_KEY_ID/" ./.env
RUN sed -i "s/secret-key/$REACT_APP_SECRET_ACCESS_KEY/" ./.env
RUN npm ci --silent
RUN npm install react-scripts#3.4.1 -g --silent
COPY . ./
RUN npm run build
# production environment
FROM nginx:stable-alpine
COPY --from=build /app/build /usr/share/nginx/html
# new
COPY nginx/nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
My DEFAULT.env file
REACT_APP_ACCESS_KEY_ID="access-key"
REACT_APP_SECRET_ACCESS_KEY="secret-key"
My Build command used
docker build -f Dockerfile.prod --build-arg REACT_APP_ACCESS_KEY_ID=ABCDEFGHZXCV --build-arg REACT_APP_SECRET_ACCESS_KEY=ABCDEFGHZXCVhdhjshdjsdf9889 -t test:prod .
The build command keeps warning:
One or more build-args [REACT_APP_ACCESS_KEY_ID
REACT_APP_SECRET_ACCESS_KEY] were not consumed.
For some reason the sed command is not picking them up, so must be sed syntax. I am open to other possibilities of creating the .env file.
You need to define arguments inside your Dockerfile before it's usage, using ARG:
https://docs.docker.com/engine/reference/builder/#arg
I want to run docker container with sidecar by this tutorial.
For example, i have java spring boot application. Then i made such Dockerfile:
# Dockerfile for GitLab CI/CD
FROM maven:3.5.2-jdk-8-alpine AS MAVEN_BUILD
ARG SPRING_ACTIVE_PROFILE
MAINTAINER SlandShow
COPY pom.xml /build/
COPY src /build/src/
WORKDIR /build/
RUN mvn clean install -Dspring.profiles.active=$SPRING_ACTIVE_PROFILE && mvn package -B -e -Dspring.profiles.active=$SPRING_ACTIVE_PROFILE
FROM openjdk:8-alpine
WORKDIR /app
COPY --from=MAVEN_BUILD /build/target/task-0.0.1-SNAPSHOT.jar /app/task-0.0.1-SNAPSHOT.jar
ENTRYPOINT ["java", "-jar", "task-0.0.1-SNAPSHOT.jar"]
After that i build docker image and run it:
$ docker build .
$ docker container run -p 8010:8010 <imageId>
Docker-CLI returns hash for started contaner. For example- cc82fa748a62de634893f5594a334ada2854f0be0dff8149efb28ae67c98191c.
Then i'am trying to start sidecar:
docker run -pid=container:cc82fa748a62de634893f5594a334ada2854f0be0dff8149efb28ae67c98191c -p 8080:8080 brendanburns/topz:db0fa58 /server --addr=0.0.0.0:8080
And get:
docker: invalid publish opts format (should be name=value but got '8080:8080').
What's wrong with it?
My fault, i forgot - before -p...
Here is my Dockerfiles which work, but my image is heavy.
I would like to unzip only on start! How can I do that?
I would like to execute dockerStatScript.sh just on start, and after "pm2-runtime", "pm2_conf.json"
I have try everything... I don't get it
thank for your help
FROM keymetrics/pm2:12-alpine
RUN apk add --no-cache --upgrade bash && \
apk add postgresql-libs libpq zip unzip tree
WORKDIR /app
COPY docker/dockerStatScript.sh .
RUN chmod +x dockerStatScript.sh
ENV NODE_ENV=production
COPY app_prod/build/2.6.3/app.zip Zapp.zip
COPY app_prod/build/2.6.3/node_modules.zip Znode_modules.zip
COPY app_prod/build/2.6.3/config.zip Zconfig.zip
RUN ["/bin/bash","dockerStatScript.sh"]
CMD [ "pm2-runtime", "pm2_conf.json" ]
EXPOSE 8080
To compress immage use
docker image build --compress {rest-of-the-build-arguments-here}
to start dockerStatScript.sh after "pm2-runtime", "pm2_conf.json"
you will have to create a wrapper shell script like startup.sh with content
./pm2-runtime.sh pm2_conf.json
./dockerStatScript.sh
add it to the docker image like you did for dockerStatScript.sh. i.e.
COPY docker/startup.sh .
RUN chmod +x startup.sh
and than replace these:
RUN ["/bin/bash","dockerStatScript.sh"]
CMD [ "pm2-runtime", "pm2_conf.json" ]
with this:
ENTRYPOINT ["/bin/bash","/app/startup.sh"]
and start container with out parameters because entrypoint going to "startup.sh" on each container start.
here is a helpful link which explains startup options:
https://dev.to/lasatadevi/docker-cmd-vs-entrypoint-34e0.
hope i didn't do any typos :)
UPDATE:
you can use
ENTRYPOINT ["/bin/bash","/app/startup.sh"]
or
CMD ["/bin/bash","/app/startup.sh"]
or omit entrypoint and cmd and just start container with /app/startup.sh as parameter. i.e. docker run image-name "/app/startup.sh" - i am usually using this wa because it gives more flexibility what to run during debug time.
Make sure that your sh file doesn't exit until you need your container to stop.
Using the docker build command line I can pass in a build secret as follows
docker build \
--secret=id=gradle.properties,src=$HOME/.gradle/gradle.properties \
--build-arg project=template-ms \
.
Then use it in a Dockerfile
# syntax = docker/dockerfile:1.0-experimental
FROM gradle:jdk12 AS build
COPY *.gradle .
RUN --mount=type=secret,target=/home/gradle/gradle.properties,id=gradle.properties gradle dependencies
COPY src/ src/
RUN --mount=type=secret,target=/home/gradle/gradle.properties,id=gradle.properties gradle build
RUN ls -lR build
FROM alpine AS unpacker
ARG project
COPY --from=build /home/gradle/build/libs/${project}.jar /tmp
RUN mkdir -p /opt/ms && unzip -q /tmp/${project}.jar -d /opt/ms && \
mv /opt/ms/BOOT-INF/lib /opt/lib
FROM openjdk:12
EXPOSE 8080
WORKDIR /opt/ms
USER nobody
CMD ["java", "-Xdebug", "-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=0.0.0.0:8000", "-Dnetworkaddress.cache.ttl=5", "org.springframework.boot.loader.JarLauncher"]
HEALTHCHECK --start-period=600s CMD curl --silent --output /dev/null http://localhost:8080/actuator/health
COPY --from=unpacker /opt/lib /opt/ms/BOOT-INF/lib
COPY --from=unpacker /opt/ms/ /opt/ms/
I want to do a build using docker-compose, but I can't find in the docker-compose.yml reference how to pass the secret.
That way the developer just needs to type in docker-compose up
You can use environment or args to pass variables to container in docker-compose.
args:
- secret=id=gradle.properties,src=$HOME/.gradle/gradle.properties
environment:
- secret=id=gradle.properties,src=$HOME/.gradle/gradle.properties
I'm trying to configure my docker container so it's possible to ssh into it (the container will be run on Azure). I managed to create an image that enables user to ssh into a container created from that image, the Dockerfile looks like that (it's not mine, I found it on the internet):
FROM mcr.microsoft.com/dotnet/core/sdk:2.2-stretch AS build
EXPOSE 2222
RUN apt-get update && apt-get install -y openssh-server
RUN mkdir /var/run/sshd
COPY sshd_config /etc/ssh
RUN echo 'root:Docker' | chpasswd
RUN sed -i 's/PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
RUN sed 's#session\s*required\s*pam_loginuid.so#session optional pam_loginuid.so#g' -i /etc/pam.d/sshd
ENV NOTVISIBLE "in users profile"
RUN echo "export VISIBLE=now" >> /etc/profile
CMD ["/usr/sbin/sshd", "-D"]
I'm using mcr.microsoft.com/dotnet/core/sdk:2.2-stretch because it's what I need later on to run the application.
Having the Dockerfile above, I run docker build . -t ssh. I can confirm that it's possible to ssh into a container created from ssh image with following instructions:
docker run -d -p 0.0.0.0:2222:22 --name ssh ssh
ssh root#localhost -p 2222
My application's Dockerfile:
FROM mcr.microsoft.com/dotnet/core/sdk:2.2-stretch AS build
WORKDIR /src
COPY ["Application.WebAPI/Application.WebAPI.csproj", "Application.WebAPI/"]
COPY ["Processing.Dependency/Processing.Dependency.csproj", "Processing.Dependency/"]
COPY ["Processing.QueryHandling/Processing.QueryHandling.csproj", "Processing.QueryHandling/"]
COPY ["Model.ViewModels/Model.ViewModels.csproj", "Model.ViewModels/"]
COPY ["Core.Infrastructure/Core.Infrastructure.csproj", "Core.Infrastructure/"]
COPY ["Model.Values/Model.Values.csproj", "Model.Values/"]
COPY ["Sql.Business/Sql.Business.csproj", "Sql.Business/"]
COPY ["Model.Events/Model.Events.csproj", "Model.Events/"]
COPY ["Model.Messages/Model.Messages.csproj", "Model.Messages/"]
COPY ["Model.Commands/Model.Commands.csproj", "Model.Commands/"]
COPY ["Sql.Common/Sql.Common.csproj", "Sql.Common/"]
COPY ["Model.Business/Model.Business.csproj", "Model.Business/"]
COPY ["Processing.MessageBus/Processing.MessageBus.csproj", "Processing.MessageBus/"]
COPY [".Processing.CommandHandling/Processing.CommandHandling.csproj", "Processing.CommandHandling/"]
COPY ["Processing.EventHandling/Processing.EventHandling.csproj", "Processing.EventHandling/"]
COPY ["Sql.System/Sql.System.csproj", "Sql.System/"]
COPY ["Application.Common/Application.Common.csproj", "Application.Common/"]
RUN dotnet restore "Application.WebAPI/Application.WebAPI.csproj"
COPY . .
WORKDIR "/src/Application.WebAPI"
RUN dotnet build "Application.WebAPI.csproj" -c Release -o /app
FROM build AS publish
RUN dotnet publish "Application.WebAPI.csproj" -c Release -o /app
FROM ssh AS final
WORKDIR /app
EXPOSE 80
EXPOSE 443
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "Application.WebApi.dll"]
As you can see I'm using ssh image as a base image in the final stage. Even though I was able to sshe into the container created from ssh image, I'm unable to ssh into a container created from the latter Dockerfile. Here is the docker-compose.yml I'm using in order to ease starting the container:
version: '3.7'
services:
application.webapi:
image: application.webapi
container_name: webapi
ports:
- "0.0.0.0:5000:80"
- "0.0.0.0:2222:22"
build:
context: .
dockerfile: Application.WebAPI/Dockerfile
environment:
- ASPNETCORE_ENVIRONMENT=docker
When I run docker exec -it webapi bashand execute service ssh status, I'm getting [FAIL] sshd is not running ... failed! - but when I do service ssh start and try to ssh into that container, it works. Unfortunately this approach is not acceptable, ssh daemon should launch itself on startup.
I tried using cron and other stuff available on debian but it's a slim version and systemd is not available there - I'm also not fond of installing hundreds of things on slim versions.
Do you have any ideas what could be wrong here?
You have conflicting startup command definitions in your final image. Note that CMD does not simply run a command in your image, it defines the startup command, and has a complex interaction with ENTRYPOINT (in short: if both are present, CMD just supplies extra arguments to ENTRYPOINT).
You can see the table of possibilities in the Dockerfile documentation: https://docs.docker.com/engine/reference/builder/. In addition, there's a bonus complication when you mix and match CMD and ENTRYPOINT in different layers:
Note: If CMD is defined from the base image, setting ENTRYPOINT will reset CMD to an empty value. In this scenario, CMD must be defined in the current image to have a value.
As far as I know, you can't get what you want just by layering images. You will need to create a startup script in your final image that both runs sshd -D and then runs dotnet Application.WebApi.dll.