Install Sdkman in an Alpine based Docker Image - docker

I need to install Sdkman in an Alpine based docker image, but there is a problem that default shell is not Bash. Then command:
source "$HOME/.sdkman/bin/sdkman-init.sh"
ends with failure:
/bin/sh: /root/.sdkman/bin/sdkman-init.sh: line 40: SDKMAN_PLATFORM+=64: not found

You'll need to split the install of SDKMAN and running the init script into two RUN blocks e.g.
RUN apk add bash curl git zip && \
curl -s "https://get.sdkman.io" | bash
RUN bash -c "source $HOME/.sdkman/bin/sdkman-init.sh && sdk version"
Source: https://e.printstacktrace.blog/using-sdkman-as-a-docker-image-for-jenkins-pipeline-a-step-by-step-guide/

Related

Enable scl toolset by default

I'm trying to create a docker image where the llvm-toolset-7 is automatically enabled when the image is run.
The context is this image, since it extends from rustembedded/cross:x86_64-unknown-linux-gnu, is to cross-compile to linux. Since for my purposes I need a recent version of llvm, I need the toolset to be enabled by default when I launch the machine because the cross-complilation command is run by the cross cli and not manually by me.
My attempt at the Dockerfile to make this happen is:
FROM rustembedded/cross:x86_64-unknown-linux-gnu
RUN yum update -y && \
yum install centos-release-scl -y && \
yum install llvm-toolset-7 -y && \
yum install scl-utils -y && \
echo "source scl_source enable llvm-toolset-7" >> ~/.bash_profile
However, when I open the interactive shell in docker desktop, it doesn't default to the bash shell with the toolset enabled.
I'm a pretty frequent Ubuntu user but this image is CentOS based and I'm having trouble understanding toolsets.
I guess you use something like docker run -it imagename bash to enter into interactive shell.
Unfortunately, above will by default start a non-login shell, the .bash_profile only be called if it's in login shell, to make it works as login shell, you need to use next to enter into the container:
docker run -it imagename bash -l
-l Make bash act as if it had been invoked as a login shell
Minimal Example
Dockerfile:
FROM rustembedded/cross:x86_64-unknown-linux-gnu
RUN echo "export ABC=1" >> ~/.bash_profile
Execution:
$ docker build -t abc:1 .
$ docker run --rm -it abc:1 bash
[root#669149c2bc8b /]# env | grep ABC
[root#669149c2bc8b /]#
[root#669149c2bc8b /]# exit
$ docker run --rm -it abc:1 bash -l
[root#7be9b9b8e906 /]# env | grep ABC
ABC=1
You can see with -l to make it as login shell, .bash_profile be executed.

Ruby-Rails in Docker exits after docker run

I have created a Dockerfile based on the description to create a rails application in Linux. Currently, I have two problems with the current setting:
First, I get the error or warning after every RUN command starting with the environment variable $shell. The error looks like this:
mesg: ttyname failed: Inappropriate ioctl for device
Second, my container stops directly after starting it with
docker run -d --name rails rails:test
My current docker file looks like this:
FROM ubuntu:18.04
RUN mkdir /usr/src/rails
WORKDIR /usr/src/rails
RUN apt-get update && apt-get install -y curl gnupg
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
RUN apt-get update && apt install -y yarn
RUN curl -sSL https://get.rvm.io | bash
RUN useradd -G rvm rails
ENV shell /bin/bash -l -c
#RUN . /usr/local/rvm/scripts/rvm
RUN echo ". /etc/profile.d/rvm.sh" >> ~/.bashrc
RUN $shell "rvm requirements"
RUN $shell "rvm install ruby"
RUN echo "gem: --no-rdoc --no-ri" >> ~/.gemrc
RUN $shell "gem install rails"
RUN $shell "ruby -v" && $shell "rails -v"
USER rails
EXPOSE 3000
#CMD ["rails", "server", "-b", "0.0.0.0"]
CMD ["/bin/bash"]
The solution with the $shell variable I found on another website. Without the command /bin/bash -l -c the build process will fail. The command rvm or gem will be unknown. The mentioned command will be used as a wrapper around the real command inside the quotes. I do not really understand why this is necessary. If I create a docker container and execute the commands like they are in the Dockerfile, then everything works fine. Why it is not working as I execute the command inside of the Dockerfile script?
Since I use the wrapper command, everything works well, but I get this error or warning message mentioned above. The image will be made, so this is more like a minor problem. The main problem is, that my container doesn't start. If I type the command docker run -d rails:test the container will be exited directly after. I do not really understand why. Does anyone have some explanations?

Use STDIN during docker build from a Dockerfile

I'm trying to install Miniconda in a docker image as a first step, right now this is what I have:
FROM ubuntu:14.04
RUN apt-get update && apt-get install wget
RUN wget *miniconda download URL* && bash file_downloaded.sh
When I try to build the image, it goes well until it starts popping the following message continously:
>>> Please answer 'yes' or 'no'
At that point I need to stop docker build. How can I fix it? Should I include something in the dockerfile?
You can't attach interactive tty during image build. If it is asking for 'yes' or 'no' during package installation, wget in your case, you can replace the corresponding line with RUN apt-get update -qq && apt-get install -y wget. If it is bash file_downloaded.sh, check if file_downloaded.sh accepts 'yes' or 'no' as a command line argument.
If file_downloaded.sh doesn't have that option, create a container from ubuntu:14.04 image, install wget and run your commands manually there. Then, you can make an image of the container by committing your changes like: docker commit <cotainer_id> <image_name>.
I believe you can pass -b flag to miniconda shell script to avoid manual answering
Installs Miniconda3 4.0.5
-b run install in batch mode (without manual intervention),
it is expected the license terms are agreed upon
-f no error if install prefix already exists
-h print this help message and exit
-p PREFIX install prefix, defaults to $PREFIX
something like that:
RUN wget http://......-x86_64.sh -O miniconda.sh
RUN chmod +x miniconda.sh \
&& bash ./miniconda.sh -b

Docker CMD doesn't see installed components

I am trying to build a docker image using the following docker file.
FROM ubuntu:latest
# Replace shell with bash so we can source files
RUN rm /bin/sh && ln -s /bin/bash /bin/sh
# Update packages
RUN apt-get -y update && apt-get install -y \
curl \
build-essential \
libssl-dev \
git \
&& rm -rf /var/lib/apt/lists/*
ENV APP_NAME testapp
ENV NODE_VERSION 5.10
ENV SERVE_PORT 8080
ENV LIVE_RELOAD_PORT 8888
# Install nvm, node, and angular
RUN (curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.1/install.sh | bash -) \
&& source /root/.nvm/nvm.sh \
&& nvm install $NODE_VERSION \
&& npm install -g angular-cli \
&& ng new $APP_NAME \
&& cd $APP_NAME \
&& npm run postinstall
EXPOSE $SERVE_PORT $LIVE_RELOAD_PORT
WORKDIR $APP_NAME
EXPOSE 8080
CMD ["node", "-v"]
But I keep getting an error when trying to run it:
docker: Error response from daemon: Container command 'node' not found or does not exist..
I know node is being properly installed because if I rebuild the image by commenting out the CMD line from the docker file
#CMD ["node", "-v"]
And then start a shell session
docker run -it testimage
I can see that all my dependencies are there and return proper results
node -v
v5.10.1
.....
ng -v
angular-cli: 1.0.0-beta.5
node: 5.10.1
os: linux x64
So my question is. Why is the CMD in Dockerfile not able to run these and how can I fix it?
When using the shell to RUN node via nvm, you have sourced the nvm.sh file and it will have a $PATH variable set in it's environment to search for executable files via nvm.
When you run commands via docker run it will only inject a default PATH
docker run <your-ubuntu-image> echo $PATH
docker run <your-ubuntu-image> which node
docker run <your-ubuntu-image> nvm which node
Specifying a CMD with an array execs a binary directly without a shell or a $PATH to lookup.
Provide the full path to your node binary.
CMD ["/bin/node","-v"]
It's better to use the node binary rather than the nvm helper scripts due to the way dockers signal processing works. It might be easier to use the node apt packages in docker rather than nvm.

Identical dockerfiles giving different behaviours

I am using the following dockerfile taken from (http://txt.fliglio.com/2013/11/creating-a-mysql-docker-container/):
FROM ubuntu
RUN dpkg-divert --local --rename --add /sbin/initctl
RUN ln -s /bin/true /sbin/initctl
RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list
RUN apt-get update
RUN apt-get upgrade -y
RUN apt-get -y install mysql-client mysql-server
RUN sed -i -e"s/^bind-address\s*=\s*127.0.0.1/bind-address = 0.0.0.0/"
/etc/mysql/my.cnf
ADD ./startup.sh /opt/startup.sh
EXPOSE 3305
CMD ["/bin/bash", "/opt/startup.sh"]
This works with no errors when I build on Docker version 0.8 on my local machine.
I have been experimenting with trusted builds:
https://index.docker.io/u/hardingnj/sqlcontainer/
however on the docker servers I get an error with the second RUN command:
[91mln: failed to create symbolic link `/sbin/initctl': File exists
[0m
Error: build: The command [/bin/sh -c ln -s /bin/true /sbin/initctl] returned a non-zero code: 1
I was under the impression that Dockerfiles should work identically independently of context? Perhaps the versions of ubuntu that I am pulling aren't identical?
It is possible that the versions of the ubuntu image are different. To be extremely precise you could give the full image id that you want in the FROM statement, e.g.
# This is the id of the current Ubuntu 13.10 image.
# The tag could move to a different image at a later time.
FROM 9f676bd305a43a931a8d98b13e5840ffbebcd908370765373315926024c7c35e
RUN dpkg-divert --local --rename --add /sbin/initctl
...

Resources