Ruby-Rails in Docker exits after docker run - ruby-on-rails

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?

Related

Dockerfile hide output of RUN command

If I have a few RUN commands in my Dockerfile, how can I have it not print any output from a specific command, such as ignoring the printed statements from an apt-get update?
This works for me
FROM ubuntu:16.04
RUN which nano || echo no nano
RUN bash -c "apt-get update &> /dev/null"
RUN bash -c "apt-get install nano &> /dev/null"
RUN which nano
(really got the solution from Redirecting command output in docker)

linux source command not working when building Dockerfile

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.

Why does docker overwrite everything I've installed?

I've got a rails proxy app that runs with jupyter notebooks, and I'm trying to get a docker image up and running with supervisor as the entry point.
However, after including a FROM jupyter/notebook, everything I did to set up the rails is gone!
My dockerfile
#Installs Jupyter Notebook and IPython kernel from the current branch
# Another Docker container should inherit with `FROM jupyter/notebook`
# to run actual services.
# For RVM support - ultimately do out own solution here.
FROM tzenderman/docker-rvm:latest
# Update aptitude
RUN apt-get update
# Install software
RUN apt-get install -y git supervisor libgmp3-dev
# Set up loggin for now
RUN mkdir -p /var/log/supervisor
# USING TOKENS ###################################################
ARG DEPLOYMENT_TOKEN
RUN git clone https://$DEPLOYMENT_TOKEN:x-oauth-basic#github.com/proversity-org/edx-api-jupyter.git /tmpapp/
RUN mkdir /home/sifu/
RUN cp -R /tmpapp/* /home/sifu/
RUN cp -R -r /tmpapp/. /home/sifu/
RUN chown root:root -R /home/sifu/
#################################################################
WORKDIR /home/sifu
# Install ruby using RVM
RUN /bin/bash -l -c "rvm install $(cat .ruby-version) --verify-downloads"
RUN /bin/bash -l -c "rvm use $(cat .ruby-version) --default"
RUN /bin/bash -l -c "rvm list"
RUN rvm requirements
# run docker env for ruby apps
RUN /bin/bash -l -c "source .docker-ruby-version"
RUN echo $RUBY-VERSION
ENV GEM_HOME /usr/local
ENV PATH /usr/local/rvm/gems/ruby-2.2.3/bin:$PATH
ENV PATH /usr/local/rvm/rubies/ruby-2.2.3/bin:$PATH
# Install Bundler
RUN ruby --version
RUN gem install bundler
RUN bundle config --global silence_root_warning 1
# Install Sifu gems
RUN bundle install --gemfile=/home/sifu/Gemfile
# Alow for arugments to sifu & notebook (server ip & port etc)
#RUN /bin/bash -l -c "which bundle"
#RUN /bin/bash -l -c "cp $(which ruby) /usr/bin/"
# Set up supervisor config -- move this up later
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
# Set as environment variables
FROM jupyter/notebook
CMD ["/usr/bin/supervisord"]
ENTRYPOINT ["/usr/bin/supervisord", "-c", "/etc/myapp/supervisord.conf"]
All the software I installed is gone, when I use a FROM jupyter/notebook to include the notebooks in the image.
Is there something crucial I am missing?

Cannot start a docker container

This is my Dockerfile, which attempts to setup Nginx with Phusion Passenger, and then install Ruby.
# Build command: docker build --force-rm --tag="rails" .
# Run command: docker run -P -d rails
FROM ubuntu:14.04
ENV DEBIAN_FRONTEND noninteractive
# Install nginx and passenger
RUN sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 561F9B9CAC40B2F7
RUN sudo sudo apt-get install -yf apt-transport-https ca-certificates
RUN sudo echo 'deb https://oss-binaries.phusionpassenger.com/apt/passenger trusty main' > /etc/apt/sources.list.d/passenger.list
RUN sudo chown root: /etc/apt/sources.list.d/passenger.list
RUN sudo chmod 600 /etc/apt/sources.list.d/passenger.list
RUN sudo apt-get update
RUN sudo apt-get install -yf nginx-extras passenger
RUN sudo service nginx restart
# Install rbenv and ruby
RUN sudo apt-get install -yf git autoconf bison build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev libgdbm3 libgdbm-dev curl
RUN git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
RUN git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
RUN echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
RUN echo 'eval "$(rbenv init -)"' >> ~/.bashrc
RUN /root/.rbenv/plugins/ruby-build/install.sh
ENV PATH /root/.rbenv/bin:$PATH
RUN rbenv install 2.1.5
RUN rbenv global 2.1.5
EXPOSE 80
Basically, I can build the image just fine, but I cannot start a container from this image.
This is my first time using docker, so I suspect that I need to use the CMD directive, but I have no idea what command should go there.
I appreciate any help to point out what is wrong with my Dockerfile.
The container is running successfully, its just exiting immediately as you don't specify any process to run. A container will only run as long as its main process. As you've run it in the background (the -d flag) it won't provide any output, which is a bit confusing.
For example:
$ docker run ubuntu echo "Hello World"
Hello World
The container ran the command and exited as expected.
$ docker run -d ubuntu echo "Hello World"
efd8f9980c1c9489f72a576575cf57ec3c2961e312b981ad13a2118914732036
The same thing as happened, but as we ran with -d, we got the id of the container back rather than the output. We can get the output using the logs command:
$ docker logs efd8f9980c1c9489f72a576575cf57ec3c2961e312b981ad13a2118914732036
Hello World
What you need to do is start your rails app, or whatever process you want the container to run when you launch the container. You can either do this from the docker run command or using CMD statement in the Dockerfile. Note that the main process must stay in the foreground - if it forks to the background the container will exit.
If you want to get a shell in a container, start it with -it e.g:
$ docker run -it ubuntu /bin/bash
To be honest, I think you'd be better served by using an official image e.g. https://registry.hub.docker.com/_/rails/.
You need to use ENTRYPOINT to start what you want, check the official documentation.
See what the logs says by issuing
docker logs rails
or, as
docker ps -an 1
should show the last id, with the command
docker logs this_id

Beanstalkd in docker

I'm building a Docker image with this Dockerfile
FROM ubuntu:12.04
ENV DEBIAN_FRONTEND noninteractive
ENV PATH /usr/local/rvm/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# update apt
RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list
RUN apt-get update
RUN apt-get -y dist-upgrade
RUN apt-get install -y beanstalkd
RUN sed -i 's/\#START=yes/START=yes/g' /etc/default/beanstalkd
EXPOSE 11300
ENTRYPOINT service beanstalkd start
The image is successfully built and then I want to create an instance:
docker run -i -d -p 11300:11300 beanstalk /bin/bash
However, when I do docker ps -a, the instance has status Exit 0. I'm assuming that this means that the instance is not running. When I try to start it or attach to it, nothing seems to be happening.
So the question is why is the container not running?
Thanks, Michal
With service beanstalkd start you are starting the server, and then exiting. You will want to run the program directly - ENTRYPOINT /usr/local/bin/beanstalkd -l 0.0.0.0 -p 11300 -b .... (etc)

Resources