I'm upgrading a Dockerfile from Ubuntu 18.04 to 22.04. I'm using jruby for some test scripts, but unfortunately jruby is not in the apt repositories of 22.04 any more. Since I also can't find a PPA which I can use to install it I could simply download the binaries, but then I need to define a version. I just want to always get the most recent stable version, so I opted to use rvm to install it using the following lines:
RUN apt update -y
RUN apt install -y gnupg2
RUN gpg2 --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
RUN \curl -sSL https://get.rvm.io | bash -s stable --ruby=jruby
RUN ["/bin/bash", "-c", "source /usr/local/rvm/scripts/rvm"]
RUN which jruby
When I run these lines manually in the container it works great, but in the container it errors out on the last line saying:
The command '/bin/sh -c which jruby' returned a non-zero code: 1
I also tried to run the last command using bash instead of sh using the line below, but that ends in the same error:
RUN ["/bin/bash", "-c", "which jruby"]
The path to jruby which I get when I run the commands inside the container is this:
/usr/local/rvm/rubies/jruby-9.2.9.0/bin/jruby
So without knowing the installed version of jruby, I can't know the path.
How can I install jruby in a simple way, defining the version of it?
Related
I have installed ROS using
sudo apt-get install ros-desktop-full
all tutorial on the net says configure enviroment setup using command
source /opt/ros/<dist>/setup.bash
I don't find any folder with the name ros in my /opt/
I can only see only following folders after executing the command
$ ls /opt/
atom google SQLiteStudio zoom
You used the wrong apt command. You should use sudo apt install ros-<distro>-desktop-full. Assuming you're on Ubuntu20.04 and wanting to run ROS Noetic the command is sudo apt install ros-noetic-desktop-full.
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?
So I am trying to make a basic Dockerfile, but when I run this it says
The command bin/sh -c sudo apt-get install git python-yaml python-jinja2 returned a non-zero code: 1
My question is what am I doing wrong here, and is it even allowed to do commands like 'cd' and 'source' from the Dockerfile?
FROM Ubuntu
MAINTAINER example
#install and source ansible
RUN sudo apt-get update
RUN sudo apt-get install git python-yaml python-jinja2 python-pycurl
RUN sudo git clone https://github.com/ansible/ansible.git
RUN sudo cd ansible
RUN sudo source ./hacking/env-setup
Couple of pointers / comments here:
It's ubuntu not Ubuntu
From base ubuntu (and unfortunately, a lot of images) you don't need to use sudo, the default user is root (and in ubuntu, sudo is not included anyway)
You want your apt-get update and apt-get install to be RUN as part of the same command, to prevent issues with Docker's layer cache
You need to use the -y flag to apt-get install as the Docker build process runs non-interactively
Few other points I could make about clearing up your apt-cache and other non-required artifacts after running the commands, but this should be enough to get going on
New Dockerfile (taking into account the above) would look something like:
FROM ubuntu
MAINTAINER example
#install and source ansible
RUN apt-get update && apt-get install -y \
git \
python-yaml \
python-jinja2 \
python-pycurl
RUN git clone https://github.com/ansible/ansible.git
WORKDIR ansible/hacking
RUN chmod +x env-setup; sync \
&& ./env-setup
You might also find it useful to read the Dockerfile best practises.
Edit: Larsks answer also makes some useful points about the state of the container not persisting between layers so you should go upvote him too!
When building an image you're already running as root. You don't need sudo and there's a good chance it's not installed.
Along similar lines, this will never work:
RUN sudo cd ansible
The cd command only affects the current process; this would run cd and then exit, leaving you in the same directory you started in. The Docker WORKDIR directive can be used to persistently change the working directory:
WORKDIR ansible
You can also pass a series of shell commands to the RUN directive, like this:
RUN cd ansible; source ./hacking/env-setup
But even that probably won't do what you want, because like the sudo cd ... command earlier, that would modify your environment...and then exit, leaving the current environment unchanged in any subsequent commands.
If you want to run Ansible in a container, you should probably either install it, or plan to run the env-setup script manually after starting a container from the image.
I have a Dockerfile that defines a Ruby on Rails stack.
Here is the Dockerfile:
FROM ubuntu:14.04
MAINTAINER example <examplen#example.com>
# Update
RUN apt-get update
# Install Ruby and Rails dependencies
RUN apt-get install -y \
ruby \
ruby-dev \
build-essential \
libxml2-dev \
libxslt1-dev \
zlib1g-dev \
libsqlite3-dev \
nodejs \
curl
RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
RUN curl -sSL https://get.rvm.io | bash -s stable --rails
RUN /bin/bash -c "source /usr/local/rvm/scripts/rvm"
# Install Rails
RUN gem install rails
# Create a new Rails app under /src/my-app
RUN mkdir -p /src/new-app
RUN rails new /src/new-app
WORKDIR /src/my-app
# Default command is to run a rails server on port 3000
CMD ["rails", "server", "--binding", "0.0.0.0", "--port" ,"3000"]
EXPOSE 3000
When I execute the command docker build -t anotherapp/my-rails-app . I get the following error:
Removing intermediate container 3f8060cdc6f5
Step 8 : RUN gem install rails
---> Running in 8c1793414e63
ERROR: Error installing rails:
activesupport requires Ruby version >= 2.2.2.
The command '/bin/sh -c gem install rails' returned a non-zero code: 1
It looks like the command source /usr/local/rvm/scripts/rvm isn't working during the build.
I'm not sure exactly why this is happening.
From the docker builder reference, each RUN command is run independently. So doing RUN source /usr/local/rvm/scripts/rvm does not have any effect on the next RUN command.
Try changing the operations which require the given source file as follows
RUN /bin/bash -c "source /usr/local/rvm/scripts/rvm ; gem install rails"
This doesn't directly answer your question, but it's another way to approach the problem.
Docker provides an official Ruby image. This is the image the Docker Compose and Rails quickstart tutorial uses. As you can see from their example (below), you can copy your Gemfile.lock into your image and run bundle install without having to worry about RVM.
FROM ruby:2.2.0
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs
RUN mkdir /myapp
WORKDIR /myapp
ADD Gemfile /myapp/Gemfile
ADD Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
ADD . /myapp
You will normally only have one rails application running inside a container using a specific version of Ruby so RVM's ability to manage multiple version of Ruby won't be helpful.
If you are curious how the official images are made, the Dockerfile is on Github.
As to why this is happening. As others pointed out, source command executes the file in the current shell. Each RUN instruction
... will execute any commands in a new layer on top of the current image and commit the results. The resulting committed image will be used for the next step in the Dockerfile.
Each RUN, ADD, COPY instruction essentially starts a new shell in a new container and executes a command.
1 RUN /bin/bash -c "source /usr/local/rvm/scripts/rvm"
2 RUN gem install rails
Can be read as
1 Start a brand new shell
Execute: source /usr/local/rvm/scripts/rvm
Save the state of the file system as an image
Exit shell
2 Start a brand new shell
Execute: gem install rails
...
When step 1 finishes, the shell (and everything your sourced into it), goes away.
I created a docker container from my OS X VM Docker host. I created it using the run command and created the container based off the ubuntu:xenial image off docker hub.
I'm now connected to my container after it's created and logged in as root and at the command prompt inside my container.
I tried to install homebrew and for some reason, I can't run the command to install Homebrew:
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
when I run that I get a bash:
curl: command not found
Not sure why I'm not able to use curl here inside my container.
curl: command not found
is a big hint, you have to install it with :
apt-get -y update; apt-get -y install curl
Ran into this same issue while using the CURL command inside my Dockerfile. As Gilles pointed out, we have to install curl first. These are the commands to be added in the 'Dockerfile'.
FROM ubuntu:16.04
# Install prerequisites
RUN apt-get update && apt-get install -y \
curl
CMD /bin/bash
So I added curl AFTER my docker container was running.
(This was for debugging the container...I did not need a permanent addition)
I ran my image
docker run -d -p 8899:8080 my-image:latest
(the above makes my "app" available on my machine on port 8899) (not important to this question)
Then I listed and created terminal into the running container.
docker ps
docker exec -it my-container-id-here /bin/sh
If the exec command above does not work, check this SOF article:
Error: Cannot Start Container: stat /bin/sh: no such file or directory"
then I ran:
apk
just to prove it existed in the running container, then i ran:
apk add curl
and got the below:
apk add curl
fetch http://dl-cdn.alpinelinux.org/alpine/v3.8/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.8/community/x86_64/APKINDEX.tar.gz
(1/5) Installing ca-certificates (20171114-r3)
(2/5) Installing nghttp2-libs (1.32.0-r0)
(3/5) Installing libssh2 (1.8.0-r3)
(4/5) Installing libcurl (7.61.1-r1)
(5/5) Installing curl (7.61.1-r1)
Executing busybox-1.28.4-r2.trigger
Executing ca-certificates-20171114-r3.trigger
OK: 18 MiB in 35 packages
then i ran curl:
/ # curl
curl: try 'curl --help' or 'curl --manual' for more information
/ #
Note, to get "out" of the drilled-in-terminal-window, I had to open a new terminal window and stop the running container:
docker ps
docker stop my-container-id-here
APPEND:
If you don't have "apk" (which depends on which base image you are using), then try to use "another" installer. From other answers here, you can try:
apt-get -qq update
apt-get -qq -y install curl
This is happening because there is no package cache in the image, you need to run:
apt-get -qq update
before installing packages, and if your command is in a Dockerfile, you'll then need:
apt-get -qq -y install curl
After that install ZSH and GIT Core:
apt-get install zsh
apt-get install git-core
Getting zsh to work in ubuntu is weird since sh does not understand the source command. So, you do this to install zsh:
wget https://github.com/robbyrussell/oh-my-zsh/raw/master/tools/install.sh -O - | zsh
and then you change your shell to zsh:
chsh -s `which zsh`
and then restart:
sudo shutdown -r 0
This problem is explained in depth in this issue.
If you are using an Alpine based image, you should do
RUN
... \
apk add --no-cache curl \
curl ...
...
You don't need to install curl to download the file into Docker container, use ADD command, e.g.
ADD https://raw.githubusercontent.com/Homebrew/install/master/install /tmp
RUN ruby -e /tmp/install
Note: Add above lines to your Dockerfile file.
Another example which installs Azure CLI:
ADD https://aka.ms/InstallAzureCLIDeb /tmp
RUN bash /tmp/InstallAzureCLIDeb
what worked successfully for me was:
FROM ubuntu:20.0.4
RUN apt-get update &&\
apt-get install -y curl
...
You could base your image on one that already has curl.
A minimalistic one:
FROM alpine/curl
or a full-fledged one:
FROM rockylinux:9