Execute multiple SSH Commands from Bash on remote Docker container - linux

Hi I have 3 Docker containers A, B and C. I need to execute a .sh file embedded in A which should go something like this:
!#/bin/bash
ssh root#containerIP "mkdir /path/to/dir"
ssh root#containerIP "touch someFile.txt"
....
My Dockerfiles for B & C are:
FROM node
RUN apt-get update
# RUN apk add --update --no-cache openssh
COPY docker-entrypoint.sh /docker-entrypoint.sh
RUN chmod +x /docker-entrypoint.sh
RUN apt-get install -y openssh-server
ENTRYPOINT ["sh", "/docker-entrypoint.sh"]
WORKDIR /home/debian
COPY ./ /home/debian
RUN git init
RUN git clone --branch master https://github.com/SamLProgrammer/LAB1SD.git
WORKDIR /home/debian/LAB1SD
RUN npm install
CMD ["node", "index.js"]
and Dockerfile for middleware A is:
FROM node
RUN apt-get update
WORKDIR /home/debian
COPY ./ /home/debian
RUN git init
RUN git clone --branch another https://github.com/SamLProgrammer/DockerMiddlewareLab1.git
WORKDIR /home/debian/DockerMiddlewareLab1
RUN npm install
CMD ["node", "index.js"]
My problem is that I dont know the remote servers (B & C) ssh key. And all the process needs to be automated.
So, as far as I know, creating an ssh key-gen is not an option since it generates a ssh key on remote servers (B & C) and then I need to copy that key file in the "Middleware Server" (A). but in the proces I will be asked for (A) ssh password which I wont be able to input manually because of not having access to B & C terminals.
That's why Im thinking of creating a .txt file which contains the ssh key for (B & C) before I run the Docker Images as Containers and set it as their key, so my middleware (A) can know that ssh key and execute SSH commands using sshpass or something like that.
How can I achieve this? how can I set the ssh key from a .txt file when I run the docker Images?.
Or am I planning this in a very wrong way? and what would be the correct one to achieve making those ssh commands autmoated just by calling the bash in my situation?
I'm fairly noob at these automation infrastructures workarounds, any suggestion would help me a lot. Thanks

Related

How can i execute 2 seperate commands in a Dockerfile?

I have a Dockerfile that installs multiple services on a ubuntu baseimage such as npm, nodejs and ssh.
I want be able to ssh into the container and also run a node express application.
It works perfectly to run one of that. But i cant figure out how to start both services!
To run ssh i did:
CMD ["/usr/sbin/sshd","-D"]
For the node application i clone a git repo and run:
CMD ["node" "app.js"]
Each of that runs perfectly.
But how can i execute both commands?
I tried putting them both in the CMD directive:
CMD ["/usr/sbin/sshd","-D", "node", "app.js"]
I also tried to execute one of them with RUN:
RUN node app.js
CMD ["/usr/sbin/sshd","-D"]
It executes but is than stuck at this point and doesnt continue to compute the image..
How can i execute /usr/sbin/sshd -D (which i need to run ssh) and also node app.js?
Heres the full Dockerfile:
FROM ubuntu:latest
RUN apt update && apt install openssh-server sudo -y
RUN apt install git -y
RUN apt install nodejs -y
RUN apt install npm -y
RUN npm install express
RUN npm install better-sqlite3
RUN npm install morgan
RUN echo "PermitRootLogin yes">etc/ssh/sshd_config
RUN echo 'root:root' | chpasswd
RUN git clone https://github.com/mauriceKalevra/Web2-Projekt.git
WORKDIR Web2-Projekt
RUN npm install
RUN service ssh start
EXPOSE 22
#CMD ["/usr/sbin/sshd","-D", "&&", "node", "app.js"lss" ]
CMD ["node", "app.js"]
Two options are available to do this.
Option 1
Use a shell and && to execute two commands.
FROM debian:stretch-slim as builder
CMD touch test.txt && ls
Option 2
Put all commands you want to execute in executable script entrypoint.sh and run that script in CMD
FROM debian:stretch-slim as builder
COPY entrypoint.sh /entrypoint.sh
CMD ./entrypoint.sh
entrypoint.sh
#!/bin/sh
touch test.txt
ls
EDIT
Please note, that the commands will by default be executed sequentially so the second command will only be executed after the first. If your first process does never terminate, the second one will never start. Use & to execute commands in the background. For more information on how to run commands in parallel or sequentially please see this thread.

failed run Postgres in alpine dockerfile

i am trying to deploy my Go app with Alpine in docker, I was able to use it on my Mac and then going to Production with Centos 8 got issues
here is my Dockerfile:
FROM golang:alpine
RUN apk add --no-cache postgresql
RUN apk update && apk add --no-cache gcc && apk add --no-cache libc-dev && apk add --no-cache --update make
# Set the current working Directory inside the container
WORKDIR /app
# Copy go mod and sum files
COPY go.mod go.sum ./
# Download all dependencies. they will be cached of the go.mod and go.sum files are not changed
RUN go mod download
# Copy the source from the current directory to the WORKDIR inisde the container
COPY . .
# Build the Go app
RUN go build .
RUN rm -rf /usr/local/var/postgres/postmaster.pid
// this commands below like "psql -c ;'DROP DATABASE IF EXISTS prod'"
// "psql -c ;'CREATE USER prod'"
RUN make setup
# Exporse port 3000 or 8000 to the outisde world
EXPOSE 3000..
CMD ["make", "run" ]
then i got error:
psql: error: could not connect to server: could not connect to server: No such file or directory
Is the server running locally and accepting
connections on Unix domain socket "/tmp/.s.PGSQL.5432"?
on my make setup i do the migration, create user, database
can make SUPERUSER on psql for that alpine also??
what u can see on the above syntax, is there any wrong and how to correct it? I have stuck from yesterday
Delete your original docker file's from 8th line to 20th and add these.
If your folder structure like this :
- directory
|
-> Dockerfile
-> go.mod
-> go.sum
-> go source files
# Copy go mod and sum files
COPY . /app
# Set the current working Directory inside the container
WORKDIR /app
RUN go mod download
RUN go build .
You cannot run database commands in a Dockerfile.
By analogy, consider the go generate command: you can embed special comments in your Go source code that ask the Go compiler to run programs for you, typically to generate other source files. Say you //go:generate: psql ... in your source code and run go generate ... && go install . Now you run that compiled binary on a different system. Since you're not pointing at the same database any more, the database setup is lost.
In the same way, a Dockerfile produces a compiled artifact (in this case the Docker image) and it needs to run independently of its host environment. In your example you could docker push the image you built on MacOS to a registry, and docker run it from the CentOS host without rebuilding it (and that's probably better practice for a production system).
For the specific commands you show in the question, you could put them in a database container's /docker-entrypoint-initdb.d directory, or otherwise just run them once pointing at your database. For more general-purpose database setup you might look at running a database migration tool at application startup, either in your program's main() function or in a wrapper entrypoint script.

Access raspistill / pi camera inside a Docker container

I've been trying out my Node.js app on a Raspberry Pi 3 Model B using Docker and it runs without any troubles.
The problem comes when an app dependency (raspicam) requires raspistill to make use of the camera to take a photo. Raspberry is running Debian Stretch and the pi camera is configured and tested. But I cant access it when running the app via Docker.
Basically, I build the image with Docker Desktop on a win10 64bit machine using this Dockerfile:
FROM arm32v7/node:10.15.1-stretch
ENV PATH /opt/vc/bin:/opt/vc/lib:$PATH
RUN echo "/opt/vc/lib" > /etc/ld.so.conf.d/00-vcms.conf \
&& ldconfig
# Create the app directory
ENV APP_DIR /home/app
RUN mkdir $APP_DIR
WORKDIR $APP_DIR
# Copy both package.json and package-lock.json
COPY package*.json ./
# Install app dependencies
RUN npm install
# Bundle app source
COPY . .
EXPOSE 3000
CMD ["npm", "start"]
Then in the Raspberry, if I pull the image and run it with:
docker run --privileged --device=/dev/vchiq -p 3000:3000 [my/image:latest]
I get:
Error: spawn /opt/vc/bin/raspistill ENOENT
After some researching, I also tried running with:
docker run --privileged -v=/opt/vc/bin:/opt/vc/bin --device=/dev/vchiq -p 3000:3000 [my/image:latest]
And with that command, I get:
stderr: /opt/vc/bin/raspistill: error while loading shared libraries: libmmal_core.so: cannot open shared object file: No such file or directory
Can someone share some thoughts on what changes do I have to make to the Dockerfile so that I'm able to access the pi camera from inside the Docker container? Thanks in advance.
I've had the same problem trying to work with camera interface from docker container. With suggestions in this thread I've managed to get it working with the below dockerfile.
FROM node:12.12.0-buster-slim
EXPOSE 3000
ENV PATH="$PATH:/opt/vc/bin"
RUN echo "/opt/vc/lib" > /etc/ld.so.conf.d/00-vcms.conf
COPY "node_modules" "/usr/src/app/node_modules"
COPY "dist" "/usr/src/app"
CMD ldconfig && node /usr/src/app/app.js
There are 3 main points here:
Add /opt/vc/bin to your PATH so that you can call raspistill without referencing the full path.
Add /opt/vc/lib to your config file so that raspistill can find all dependencies it needs.
Reload config file (ldconfig) during container's runtime rather than build-time.
The last point is the main reason why Anton's solution didn't work. ldconfig needs to be executed in a running container so either use similar approach to mine or go with entrypoint.sh file instead.
Try replace this from the Dockerfile:
RUN echo "/opt/vc/lib" > /etc/ld.so.conf.d/00-vcms.conf \
&& ldconfig
With the following:
ADD 00-vmcs.conf /etc/ld.so.conf.d/
RUN ldconfig
And create the file 00-vmcs.conf:
/opt/vc/lib
Edit:
If it still doesn't work, try loading a Raspbian Docker image for example balenalib/rpi-raspbian:
FROM balenalib/rpi-raspbian

Dockerize meteor application

I have a meteor application.This app works well on the Centos7 VM.
I need to create docker container of this app and install or import this container on other virtual machines.
What do ِdocker file need to save and load container on another VM?
NodeJs?
Mongodb?
MeteorJs?
Shouldn't I store Mongodb file in Docker container?
this is my docker file:
# Pull base image.
FROM node:8.11.4
# Install build tools to compile native npm modules
RUN npm install -g node-gyp
RUN apt-get install curl -y
RUN curl https://install.meteor.com/ | sh
# Create app directory
RUN mkdir -p /usr/app
COPY . /usr/app
RUN cd /usr/app/programs/server
RUN npm install
WORKDIR /usr/app
CMD ["node", "main.js"]
EXPOSE 3000
There are many ways to skin this cat ... lets assume you have researched the alternatives on how to execute a meteor app using containers by using tools which automates the below setup - meteor calls their version of this automation Galaxy
I suggest you run the meteor commands outside the container intended to run your app from since a meteor install is huge, slow to install and some of the libraries you may pull in, or the libraries your libraries pull in, may need c or c++ compilers so meteor and its friends do not need to get installed into your app container everytime you want to recompile your app ... your app container only needs nodejs and your bundle ... when you execute a meteor app it does not use meteor instead the app is executed using nodejs directly since at this point your code has been compiled into a bundle which is pure nodejs
Yes you would do well to put mongodb into its own container
No, no need to put MeteorJs inside your app container instead just like meteor itself those compile time tools are not needed during execution time so install MeteorJs as well as all other tools needed for a successful meteor build on your host machine which is where you execute your meteor build command
In your above Dockerfile the last statement EXPOSE 3000 will never get reached so put it before your CMD node
So outside your container get meteor installed then issue
cd /your/webapp/src
meteor build --server https://example.com --verbose --directory /webapp --server-only
above will compile your meteor project into a bundle dir living at
ls -la /webapp/bundle/
then copy into that freshly cut bundle dir your Dockerfile etc :
.bashrc
Dockerfile
bundle/
then create your container
docker build --tag localhost:5000/hygge/loudweb-admin --no-cache .
docker push localhost:5000/hygge/loudweb-admin
here is a stripped down Dockerfile
cat Dockerfile
# normal mode - raw ubuntu run has finished and base image exists so run in epoc mode
FROM ubuntu:18.04
ENV DEBIAN_FRONTEND noninteractive
ENV TERM linux
ENV NODE_VER=v8.11.4
ENV NODE_NAME=node-${NODE_VER}
ENV OS_ARCH=linux-x64
ENV COMSUFFIX=tar.gz
ENV NODE_PARENT=/${NODE_NAME}-${OS_ARCH}
ENV PATH=${NODE_PARENT}/bin:${PATH}
ENV NODE_PATH=${NODE_PARENT}/lib/node_modules
RUN apt-get update && apt-get install -y wget && \
wget -q https://nodejs.org/download/release/${NODE_VER}/${NODE_NAME}-${OS_ARCH}.${COMSUFFIX} && \
tar -xf ${NODE_NAME}-${OS_ARCH}.${COMSUFFIX}
ENV MONGO_URL='mongodb://$MONGO_SERVICE_HOST:$MONGO_SERVICE_PORT/meteor'
ENV ROOT_URL=https://example.com
ENV PORT 3000
EXPOSE 3000
RUN which node
WORKDIR /tmp
# CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf" ]
# I strongly suggest you wrap below using supervisord
CMD ["node", "main.js"]
to launch your container issue
docker-compose -f /devopsmicro/docker-compose.yml pull loudmail loud-devops nodejs-enduser
docker-compose -f /devopsmicro/docker-compose.yml up -d
here is a stripped down docker compose yaml file
version: '3'
services:
nodejs-enduser:
image: ${GKE_APP_IMAGE_ENDUSER}
container_name: loud_enduser
restart: always
depends_on:
- nodejs-admin
- loudmongo
- loudmail
volumes:
- /cryptdata6/var/log/loudlog-enduser:/loudlog-enduser
- ${TMPDIR_GRAND_PARENT}/curr/loud-build/${PROJECT_ID}/webapp/enduser/bundle:/tmp
environment:
- MONGO_SERVICE_HOST=loudmongo
- MONGO_SERVICE_PORT=$GKE_MONGO_PORT
- MONGO_URL=mongodb://loudmongo:$GKE_MONGO_PORT/test
- METEOR_SETTINGS=${METEOR_SETTINGS}
- MAIL_URL=smtp://support#${GKE_DOMAIN_NAME}:blah#loudmail:587/
links:
- loudmongo
- loudmail
ports:
- 127.0.0.1:3000:3000
working_dir: /tmp
command: /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf
Once you have your app executing using containers you can work to stop using ubuntu as your container base and use a smaller, simpler docker base image like nodejs, busybox, etc however using ubuntu is easier initially since it has ability to let you install packages from inside a running container which is nice during development
the machinations surrounding above are vast ... above is a quick copy N paste plucked from the devops side of the house with hundreds of helper binaries + scripts, config templates, tls certs ... this is a tiny glimpse into the world of getting an app to execute
#Scott Stensland answer is good, in that it explains how to manually create a docker container for Meteor.
There is a simpler way use Meteor-up (mup) http://meteor-up.com/
EASILY DEPLOY YOUR APP
Meteor Up is a production quality Meteor app deployment tool.
Install with one command:
$ npm install --global mup
You set up a simple config file, and it looks after creating the container, doing npm install, setting up ssl certs etc. Much less work than doing it by hand

Docker - Override or remove ENTRYPOINT from a base image

I'm using Docker (version 1.12.2, build bb80604) to setup a simple image/container with Gatling (Load Testing tool) + NodeJS. So, I pulled this Docker/Gatling base image and created my own Dockerfile to install NodeJS on it.
However, the Docker/Gatling base image above has an ENTRYPOINT already defined to call Gatling straightaway and then automatically exits the container. It looks like this:
ENTRYPOINT ["gatling.sh"]
What I'm trying to achieve is: I want to run a second command (my own NodeJS script to parse the test results), however I couldn't find a solution so far (I tried overriding the ENTRYPOINT, different combinations of ENTRYPOINT and CMD, but no success).
Here is how my current Dockerfile looks like:
FROM denvazh/gatling:2.2.3
RUN apk update \
&& apk add -U bash \
&& apk add nodejs=6.7.0-r0
COPY simulations /opt/gatling/user-files/simulations
COPY trigger-test-and-parser.sh /opt/gatling/
RUN chmod +x /opt/gatling/trigger-test-and-parser.sh
ENTRYPOINT ["bash", "/opt/gatling/trigger-test-and-parser.sh"]
Here is the command I'm using to build my image based on my Dockerfile:
docker build --no-cache -t gatling-nodejs:v8 .
And this is the command I'm using to run my container:
docker run -i -v "$PWD/results":/opt/gatling/results -v "$PWD":/opt/gatling/git.campmon.com/rodrigot/platform-hps-perf-test gatling-nodejs:v8
And this is the shellscript (trigger-test-and-parser.sh) I'd like to execute once the container starts (it should trigger Gatling and then runs my NodeJS parser):
gatling.sh -s MicroserviceHPSPubSubRatePerfTest.scala
node publish-rate-to-team-city.js
Any ideas or tweaks so I can run both commands once my container starts?
Thanks a lot!
Set ENTRYPOINT to /usr/bin/env. Then set CMD to be what you want run.
Graham's idea above worked pretty well. Thanks again!
For future reference, here is the two lines I had to add to my Dockerfile:
ENTRYPOINT ["/usr/bin/env"]
CMD ["bash", "/opt/gatling/trigger-test-and-parse-result.sh"]

Resources