Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to access Sinatra port using Docker with docker-compose run

I'm not sure how to a correctly expose the Sinatra port 4567 from Docker back to the host. Running the app locally has no issues.

The following repository show cases the issue https://gitlab.com/davidhooey/sinatra-docker

From searching I noticed the following issue Running Ruby Sinatra inside a Docker container not able to connect (via Mac host) or find commands (in different scenario)? where the --host 0.0.0.0 is passed into the rackup command. However, I'm launching the site programmatically through using Site.run!.

File tree

.
├── Dockerfile
├── Gemfile
├── Gemfile.lock
├── README.md
├── app.rb
├── docker-compose.yml
├── site.rb
└── views
    └── index.erb

app.rb

module App
    class App
        def initialize(args)
            # Do some stuff before launching site.
            # Launch site
            Site.run!
        end
    end
end

App::App.new(ARGV)

In site.rb the :bind Sinatra setting is set to 0.0.0.0.

site.rb

require 'sinatra'

module App
    class Site < Sinatra::Base
        set :bind, '0.0.0.0'
        set :static, true
        set :public_dir, File.expand_path(__dir__)

        get '/' do
            erb :'/index'
        end
    end
end

Even still the site is inaccessible when run within a Docker container.

Dockfile

FROM ruby:2.2.6

EXPOSE 4567

RUN mkdir /app
WORKDIR /app
COPY . /app

RUN gem install bundler && bundle install

CMD ["/bin/bash"]

docker-compose.yml

version: '3.2'

services:
    app:
        build: .
        hostname: app
        ports:
            - "4567:4567"
        environment:
            - RUBYOPT=-W0 -KU -E utf-8:utf-8
        volumes:
            - type: bind
              source: .
              target: /app

Local works:

ruby app.rb

Docker not so much:

docker-compose build
docker-compose run --rm app ruby app.rb

Docker run example.

$ docker-compose run --rm app ruby app.rb
[2018-07-27 14:21:10] INFO  WEBrick 1.3.1
[2018-07-27 14:21:10] INFO  ruby 2.2.6 (2016-11-15) [x86_64-linux]
== Sinatra (v2.0.3) has taken the stage on 4567 for development with backup from WEBrick
[2018-07-27 14:21:10] INFO  WEBrick::HTTPServer#start: pid=1 port=4567

Launch a bash shell into the running container to access Sinatra within the container.

$ docker exec -it aa8f64b009b0 bash
root@app:/app# curl localhost:4567
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Sinatra Docker</title>
    </head>
   <body>
        <h1>Sinatra Docker</h1>
   </body>
</html>
root@app:/app#

Any ideas are more than welcome on how to access the Sinatra port running within the container from the localhost when Sinatra is launched programmatically.

like image 585
hooinator Avatar asked Jul 26 '18 20:07

hooinator


People also ask

How do I access exposed port Docker?

Need of exposing ports. In order to make a port available to services outside of Docker, or to Docker containers which are not connected to the container's network, we can use the -P or -p flag. This creates a firewall rule which maps a container port to a port on the Docker host to the outside world.

How do I access the host port in a Docker container?

Accessing the Host With the Default Bridge Mode You just need to reference it by its Docker network IP, instead of localhost or 127.0. 0.1 . Your host's Docker IP will be shown on the inet line. Connect to this IP address from within your containers to successfully access the services running on your host.

How do Docker compose ports work?

Docker Compose exposes all specified container ports, making them reachable internally and externally from the local machine. Once again, in the PORTS column, we can find all the exposed ports. The value to the left of the arrow shows the host address where we can reach the container externally.

What port does Docker use by default?

The Docker client will default to connecting to unix:///var/run/docker.sock on Linux, and tcp://127.0.0.1:2376 on Windows. For example: tcp:// -> TCP connection to 127.0. 0.1 on either port 2376 when TLS encryption is on, or port 2375 when communication is in plain text.


1 Answers

When running an app with docker-compose run, service ports will not be mapped. This is by design, because run is meant for one-off tasks and not for booting the whole compose stack.

See documentation here:
https://docs.docker.com/compose/reference/run/

The second difference is that the docker-compose run command does not create any of the ports specified in the service configuration. This prevents port collisions with already-open ports.

To map the ports you either need to use run with --service-ports, or add a command section to your docker-compose.yml and then use docker-compose up:

Option 1 (using run):

docker-compose run --service-ports --rm app ruby app.rb -o 0.0.0.0

Option 2 (booting the whole stack):

services:
  app:
    build: .
    hostname: app
    command: ruby app.rb -o 0.0.0.0  # <-- Add this
    ports:
      - "4567:4567"
    ...

And then:

docker-compose up
like image 129
Casper Avatar answered Sep 20 '22 00:09

Casper