How to pass docker build command arguments to bash files - bash

I am passing two command line arguments to my docker file like this:
docker build . -t ros-container --build-arg UBUNTU_VERSION=bionic --build-arg ROS_VERSION=melodic
I'm able to access them in my docker file, tho I couldn't get them in my bash files. I have tried both entrypoint and cmd techniques. But, non of them helped me.
Expectation
I want to access the two arguments,UBUNTU_VERSION & ROS_VERSION, from the 'script_init.bash' file. See the project structure.
Project structure
- ros_tutorials-noetic-devel
-Dockerfile
-scripts
-script_init.bash
Dockerfile
FROM ros:melodic-perception-bionic
# install packages
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update -q && \
apt-get upgrade -yq && \
apt-get install -yq wget curl git build-essential vim sudo lsb-release locales bash-
completion
# Adjust working directory
RUN locale-gen en_US.UTF-8
RUN useradd -m -d /home/ubuntu ubuntu -p `perl -e 'print crypt("ubuntu",
"salt"),"\n"'` && \
echo "ubuntu ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
# declare ros version arg
ARG ROS_VERSION
#declare ubuntu version arg
ARG UBUNTU_VERSION
# setup environment
USER ubuntu
WORKDIR /home/ubuntu
ENV UBUNTU_V=$UBUNTU_VERSION \
ROS_V=$ROS_VERSION
ENV LANG=en_US.UTF-8 LANGUAGE=en_US:en LC_ALL=en_US.UTF-8
CMD COPY ./scripts/script_init.bash /
ENTRYPOINT ["/scripts/script_init.bash /"]
script_init.bash
#!/bin/bash
set -e
export UBUNTU_CODENAME=$UBUNTU_V
export REPO_DIR=$(dirname "$SCRIPT_DIR")
export CATKIN_DIR="$HOME/catkin_ws"
export ROS_DISTRO=$ROS_V

You need to copy the script file into your docker image and execute it correctly.
You should be able to get it working by using this Dockerfile, note the lines at the bottom:
FROM ros:melodic-perception-bionic
# install packages
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update -q && \
apt-get upgrade -yq && \
apt-get install -yq \
bash-completion \
build-essential \
curl \
git \
locales \
lsb-release \
sudo \
vim \
wget
# Adjust working directory
RUN locale-gen en_US.UTF-8
RUN useradd -m -d /home/ubuntu ubuntu -p `perl -e 'print crypt("ubuntu", "salt"),"\n"'` && \
echo "ubuntu ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
# declare ros version arg
ARG ROS_VERSION
#declare ubuntu version arg
ARG UBUNTU_VERSION
# setup environment
USER ubuntu
WORKDIR /home/ubuntu
ENV UBUNTU_V=$UBUNTU_VERSION \
ROS_V=$ROS_VERSION
ENV LANG=en_US.UTF-8 LANGUAGE=en_US:en LC_ALL=en_US.UTF-8
# Copy your scripts directory into the docker image
COPY --chown=ubuntu:ubuntu scripts scripts
# Make sure you have execute permissions on the script
RUN chmod +x "./scripts/script_init.bash"
# Set your entrypoint to execute the script
ENTRYPOINT ["./scripts/script_init.bash"]
As a note, you could export all of these environment variables in the Dockerfile during the build without needing to execute a script at runtime, e.g. in your dockerfile:
# Export environment variables in Dockerfile
ENV UBUNTU_CODENAME=$UBUNTU_VERSION
ENV REPO_DIR=/home/ubuntu/scripts
ENV CATKIN_DIR=/home/ubuntu/catkin_ws
ENV ROS_DISTRO=$ROS_VERSION

I have finally found a solution that works like charm! Once you add the script folder, you can run it with bash command. In this way, you can pass what ever arguments to any bash file within the script folder.
# setup base image
FROM ros:melodic-perception-bionic
# install packages
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update -q && \
apt-get upgrade -yq && \
apt-get install -yq wget curl git build-essential vim sudo lsb-release locales bash-completion
# Adjust working directory
RUN locale-gen en_US.UTF-8
RUN useradd -m -d /home/ubuntu ubuntu -p `perl -e 'print crypt("ubuntu", "salt"),"\n"'` && \
echo "ubuntu ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
# declare ros version arg
ARG ROS_VERSION
#declare ubuntu version arg
ARG UBUNTU_VERSION
# setup environment
USER ubuntu
WORKDIR /home/ubuntu
ENV UBUNTU_V=$UBUNTU_VERSION \
ROS_V=$ROS_VERSION
ENV LANG=en_US.UTF-8 LANGUAGE=en_US:en LC_ALL=en_US.UTF-8
# call script files
ADD /scripts /scripts
RUN bash /scripts/script_init.bash

Related

Run interactive docker with entrypoint [duplicate]

This question already has answers here:
Activate conda environment in docker
(14 answers)
Closed last year.
I am trying to build a docker image with a conda environment and start the environment when I start a container, but I cannot figure out how to. My Dockerfile is currently:
FROM nvidia/cuda:10.2-cudnn7-runtime-ubuntu18.04
ENV PATH="/root/miniconda3/bin:${PATH}"
ARG PATH="/root/miniconda3/bin:${PATH}"
RUN apt update \
&& apt install -y htop python3-dev wget git imagemagick
RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh \
&& mkdir root/.conda \
&& sh Miniconda3-latest-Linux-x86_64.sh -b \
&& rm -f Miniconda3-latest-Linux-x86_64.sh \
&& conda create -y -n .venv python=3.7
RUN /bin/bash -c "source activate .venv \
&& pip install -r requirements.txt"
# More omitted installs
CMD ["/bin/bash", "source activate .venv"]
RUN /bin/bash -c "source activate .venv"
And then I build and run with:
docker build -f Dockerfile -t adlr .
docker run -it adlr /bin/bash
-->The conda environment is not being activated upon starting the container, but I would like it to be.
You can activate the environment upon starting the container by replacing the last line of the Dockerfile with:
RUN echo "source activate .venv" >> ~/.bashrc

How to Start ssh-agent in Dockerfile

When entering my container, I want to log in as user ryan in directory /home/ryan/cas with the command eval "$(ssh-agent -c)" run. My following Dockerfile:
FROM ubuntu:latest
ENV TZ=Australia/Sydney
RUN set -ex; \
# NOTE(Ryan): Prevent docker build hanging on timezone confirmation
ln -sf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone; \
apt update; \
apt install -y --no-install-recommends \
sudo ca-certificates git gnupg openssh-client vim; \
useradd -m ryan -g sudo; \
printf "ryan ALL=(ALL:ALL) NOPASSWD:ALL" | sudo EDITOR="tee -a" visudo; \
# NOTE(Ryan): Prevent sudo usage prompt appearing on startup
touch /home/ryan/.sudo_as_admin_successful; \
git clone https://github.com/ryan-mcclue/cas.git /home/ryan/cas; \
chmod 777 -R /home/ryan/cas;
ENTRYPOINT ["/bin/bash", "-l", "-c"]
USER ryan
WORKDIR /home/ryan/cas
CMD eval "$(ssh-agent -s)"
However, running ssh-add I still get the Could not open a connection to your authentication agent which is indicative that the ssh-agent is not running. Manually typing eval "$(ssh-agent -c)" works.
I think you want remove your ENTRYPOINT statement, and then you want:
USER ryan
WORKDIR /home/ryan/cas
CMD ["ssh-agent", "bash", "-l"]
This will get you a login shell, run under the control of ssh-agent (so you'll have the necssary SSH_* environment variables and an active socket available).
To understand what's happening with your container, try running from the command line:
bash -l -c 'eval $(ssh-agent -s)'
What happens? The shell exits immediately, because running ssh-agent -s causes the agent to background itself, which looks pretty much the same as "exiting". Since you passed the -c flag, and the command given to -c has exited, the parent bash shell exits as well.

docker container nginx start but keeps hanging

my dockerfile:
FROM AWS_ECR_IMAGE
RUN apt-get update && apt-get install -y \
cron \
python-dev \
git \
zlib1g-dev \
libffi-dev \
libssl-dev \
autotools-dev \
automake \
libbz2-dev \
libaio-dev \
libsasl2-dev \
python-pip
RUN pip install boto boto3 awscli
# Install Nginx.
RUN \
add-apt-repository -y ppa:nginx/stable && \
apt-get update && \
apt-get install -y nginx && \
rm -rf /var/lib/apt/lists/* && \
echo "\ndaemon off;" >> /etc/nginx/nginx.conf && \
chown -R www-data:www-data /var/lib/nginx
# Define mountable directories.
VOLUME ["/etc/nginx/sites-enabled", "/etc/nginx/certs", "/etc/nginx/conf.d", "/var/log/nginx", "/var/www/html"]
# Define working directory.
WORKDIR /etc/nginx
# Define default command.
CMD ["nginx"]
COPY nginx_conf /etc/nginx/sites-available/default
# Start service, replace server name, update web ui
COPY main.sh /opt/annotation-pipeline-docs/main.sh
RUN chmod 0755 /opt/annotation-pipeline-docs/main.sh
ENTRYPOINT [ "sh", "-c", "/opt/annotation-pipeline-docs/main.sh" ]
# Expose ports.
EXPOSE 80
And my entrypoint bash file (I need to update the server name first when the container runs) is:
#!/bin/bash -e
/usr/local/bin/aws s3 sync s3://${S3_Bucket}/docs/${ENVIRONMENT}/HEAD/ /var/www/html/
if [ "$ENVIRONMENT" == "prod" ]
then
sed -i.bak "s/REPLACE_ME/example.com/g" /etc/nginx/sites-available/default
else
sed -i.bak "s/REPLACE_ME/example-$ENVIRONMENT.com/g" /etc/nginx/sites-available/default
fi
nginx
while true; do
sleep 60
echo "s3 sync again:"
/usr/local/bin/aws s3 sync s3://${S3_Bucket}/docs/${ENVIRONMENT}/HEAD/ /var/www/html/
done
The issue is when
nginx
runs, it will hanging forever in the terminal:
and the while loop will never get called. Anyone know why is hanging and how to resolve it? Please help, tks in advanced.
The reason for my issue is waiting for the traffic, the while loop will never get called until Nginx start free the bash. However, Nginx will be running in the foreground and not release the focus.
The solution I tried is instead of letting Nginx running as a foreground service, I changed it run in the background. Since this is the only service in my container, should have no problem to do it.
the code changed is simply removed below line in my dockerfile:
echo "\ndaemon off;" >> /etc/nginx/nginx.conf
which will make Nginx as a foreground service

Why does "docker run" error with "no such file or directory"?

I am trying to run a container which runs an automated build. Here is the dockerfile:
FROM ubuntu:14.04
MAINTAINER pmandayam
# update dpkg repositories
RUN apt-get update
# install wget
RUN apt-get install -y wget
# get maven 3.2.2
RUN wget --no-verbose -O /tmp/apache-maven-3.2.2.tar.gz http://archive.apache.or
g/dist/maven/maven-3/3.2.2/binaries/apache-maven-3.2.2-bin.tar.gz
# verify checksum
RUN echo "87e5cc81bc4ab9b83986b3e77e6b3095 /tmp/apache-maven-3.2.2.tar.gz" | md5
sum -c
# install maven
RUN tar xzf /tmp/apache-maven-3.2.2.tar.gz -C /opt/
RUN ln -s /opt/apache-maven-3.2.2 /opt/maven
RUN ln -s /opt/maven/bin/mvn /usr/local/bin
RUN rm -f /tmp/apache-maven-3.2.2.tar.gz
ENV MAVEN_HOME /opt/maven
# remove download archive files
RUN apt-get clean
# set shell variables for java installation
ENV java_version 1.8.0_11
ENV filename jdk-8u11-linux-x64.tar.gz
ENV downloadlink http://download.oracle.com/otn-pub/java/jdk/8u11-b12/$filename
# download java, accepting the license agreement
RUN wget --no-cookies --header "Cookie: oraclelicense=accept-securebackup-cookie
" -O /tmp/$filename $downloadlink
# unpack java
RUN mkdir /opt/java-oracle && tar -zxf /tmp/$filename -C /opt/java-oracle/
ENV JAVA_HOME /opt/java-oracle/jdk$java_version
ENV PATH $JAVA_HOME/bin:$PATH
# configure symbolic links for the java and javac executables
RUN update-alternatives --install /usr/bin/java java $JAVA_HOME/bin/java 20000 &
& update-alternatives --install /usr/bin/javac javac $JAVA_HOME/bin/javac 20000
# install mongodb
RUN echo 'deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen
' | sudo tee /etc/apt/sources.list.d/mongodb.list && \
apt-get update && \
apt-get --allow-unauthenticated install -y mongodb-org mongodb-org-s
erver mongodb-org-shell mongodb-org-mongos mongodb-org-tools && \
echo "mongodb-org hold" | dpkg --set-selections && \
echo "mongodb-org-server hold" | dpkg --set-selections && \
echo "mongodb-org-shell hold" | dpkg --set-selections &&
\
echo "mongodb-org-mongos hold" | dpkg --set-selectio
ns && \
echo "mongodb-org-tools hold" | dpkg --set-selec
tions
RUN mkdir -p /data/db
VOLUME /data/db
EXPOSE 27017
COPY build-script /build-script
CMD ["/build-script"]
I can build the image successfully but when I try to run the container I get this error:
$ docker run mybuild
no such file or directory
Error response from daemon: Cannot start container 3e8aa828909afcd8fb82b5a5ac894
97a537bef2b930b71a5d20a1b98d6cc1dd6: [8] System error: no such file or directory
what does it mean 'no such file or directory'?
Here is my simple script:
#!/bin/bash
sudo service mongod start
mvn clean verify
sudo service mongod stop
I copy it like this: COPY build-script /build-script
and run it like this: CMD ["/build-script"] not sure why its not working
Using service isn't going to fly - the Docker base images are minimal and don't support this. If you want to run multiple processes, you can use supervisor or runit etc.
In this case, it would be simplest just to start mongo manually in the script e.g. /usr/bin/mongod & or whatever the correct incantation is.
BTW the lines where you try to clean up don't have much effect:
RUN rm -f /tmp/apache-maven-3.2.2.tar.gz
...
# remove download archive files
RUN apt-get clean
These files have already been committed to a previous image layer, so doing this doesn't save any disk-space. Instead you have to delete the files in the same Dockerfile instruction in which they're added.
Also, I would consider changing the base image to a Java one, which would save a lot of work. However, you may have trouble finding one which bundles the official Oracle JDK rather than OpenJDK if that's a problem.

Installing rbenv on docker ubuntu/debian

I want to install rbenv on Docker which seems to work but I can't reload the shell.
FROM node:0.10.32-slim
RUN \
apt-get update \
&& apt-get install -y sudo
RUN \
echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers \
&& groupadd r \
&& useradd r -m -g r -g sudo
USER r
RUN \
git clone https://github.com/sstephenson/rbenv.git ~/.rbenv \
&& echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc \
&& echo 'eval "$(rbenv init -)"' >> ~/.bashrc
RUN rbenv # check if it works...
When I run this I get:
docker build .
..
Step 5 : RUN rbenv
/bin/sh: 1: rbenv: not found
From what I understand, I need to reload the current shell so I can install ruby versions. Not sure if I am on the right track.
Also see:
Using rbenv with Docker
The RUN command executes everything under /bin/sh, thus your bashrc is not evaled at any point.
use this
&& export PATH="$HOME/.rbenv/bin:$PATH" \
which would append rbenv to /bin/sh's PATH.
Full Dockerfile
FROM node:0.10.32-slim
RUN \
apt-get update \
&& apt-get install -y sudo
RUN \
echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers \
&& groupadd r \
&& useradd r -m -g r -g sudo
USER r
RUN \
git clone https://github.com/sstephenson/rbenv.git ~/.rbenv \
&& echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc \
&& echo 'eval "$(rbenv init -)"' >> ~/.bashrc \
&& export PATH="$HOME/.rbenv/bin:$PATH"
RUN rbenv # check if it works...
I'm not sure how Docker works, but it seems like maybe you're missing a step where you source ~/.bashrc, which is preventing you from having the rbenv executable in your PATH. Try adding that right before your first attempt to run rbenv and see if it helps.
You can always solve PATH issues by using the absolute path, too. Instead of just rbenv, try running $HOME/.rbenv/bin/rbenv.
If that works, it indicates that rbenv has installed successfully, and that your PATH is not correctly set to include its bin directory.
It looks from reading the other question you posted that docker allows you to set your PATH via an ENV PATH command, like this, for example:
ENV PATH $HOME/.rbenv/bin:/usr/bin:/bin
but you should make sure that you include all of the various paths you will need.

Resources