Reputation: 1501
Dockerfile:
FROM ruby:2.3.1-slim
MAINTAINER Marc Lacoursiere <[email protected]>
RUN apt-get update && apt-get install -yq nginx
RUN rm /etc/nginx/sites-enabled/default
ADD docker/sinatra.conf /etc/nginx/sites-enabled/sinatra.conf
RUN adduser app --gecos "First Last,RoomNumber,WorkPhone,HomePhone" --disabled-password
RUN mkdir /home/app/webapp
WORKDIR /tmp
COPY app/Gemfile /tmp/
COPY app/Gemfile.lock /tmp/
RUN bundle install
COPY app /home/app/webapp
RUN chown -R app:app /home/app
CMD ["nginx", "-g", "daemon off;"]
CMD ["ruby", "/home/app/webapp/app.rb"]
Sinatra.conf:
upstream app {
server 127.0.0.1:4000;
}
server {
listen 80 default_server;
server_name localhost;
error_log /var/log/nginx/localhost.error_log info;
location / {
proxy_pass http://app;
}
}
app.rb
require 'sinatra'
require 'sinatra/json'
set :port, 4000
get '/' do
json 'Hello World!'
end
Gemfile:
source 'https://rubygems.org'
gem 'sinatra', '1.4.6'
gem 'sinatra-contrib', '~> 1.4.2'
How it gets executed in bash
docker run -p 4444:80 roosoft/sinatra-example
Simply said, I am supposed to get a sinatra app answering the container's port 4000. Nginx is listening to the container's port 80 and returns what it finds on port 4000, which is the sinatra app. The container's port 80 is redirected to the local port 4444. But port 4444 returns:
curl: (52) Empty reply from server
At that point, for some obscure reason, nginx is not running in the container. To fix it, I simply have to login into the container, type service nginx start
and everything's fine. I can log out from the container and the local port 4444 returns what's expected.
If I comment out the last Dockerfile line, rebuild and restart the container, there is no sinatra app running in the container's port 4000, but nginx is running this time! Seems like nginx gets killed when I run sinatra.
What am I doing wrong? I obviously want both to run simultaneously...
Upvotes: 1
Views: 168
Reputation: 3422
You can't have multiple CMD
statements in a single Dockerfile (https://docs.docker.com/engine/reference/builder/#/cmd). If you look at the output of docker build
, you can see that every CMD
creates a new image. Each CMD
overwrites the one specified in the previous image.
If you want to run multiple processes in a Docker container, you could use a process manager like supervisord. supervisord also helps you to automatically restart the processes in case of a failure. A tutorial on how this is done can be found here:
https://docs.docker.com/engine/admin/using_supervisord/
Another (and IMHO more cleaner) solution is to start two containers. One for the Sinatra app and one for Nginx. Simply link both containers together (docker create --link ...
) or setup a network (docker network create ...
) and connect both containers to it (docker create --network ...
).
Upvotes: 1