Docker compose is a tool for running multi-container docker application. Container configuration are maintained easily with docker compose. Before proceed, know basics of docker (how to build and run simple container application).
For docker compose installation help click here https://docs.docker.com/compose/install/. Lets create simple rails application and run it with docker compose.
Define Dockerfile
Check the docker and docker-compose are installed properly.
$ docker --version Docker version 17.03.1-ce, build c6d412e $ docker-compose --version docker-compose version 1.12.0, build b31ff33
Lets build rails container by defining the Dockerfile and place it in the application root. Overall file structure.
Dockerfile
FROM ruby:2.2.0 FROM ruby:2.2.0 COPY . /my-rails-app RUN apt-get update -qq RUN apt-get install -y build-essential RUN apt-get install -y nodejs npm # for postgres RUN apt-get install -y libpq-dev ENV APP_HOME /my-rails-app WORKDIR $APP_HOME ADD . $APP_HOME/ RUN bundle install
This will create container with ruby, nodejs and pg-dev package, application will be copied to container /my-rails-app directory
Lets create nginx upstream to listen application port 3000. Create nginx folder in application root. It will contain two files nginx.conf and Dockerfile.
Dockerfile (For Nginx)
FROM nginx COPY nginx.conf /etc/nginx/nginx.conf
nginx.conf (To listen application port 3000)
worker_processes 4; events { worker_connections 1024; } http { upstream web-app { least_conn; server app:3000 weight=10 max_fails=3 fail_timeout=30s; } server { listen 80; location / { proxy_pass http://web-app; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; } } }
Note the upstream, its listening web container port 3000.
Define Docker Compose file
Lets define web, db and app containers and link them to make it work together.
docker-compose.yml
webserver: build: ./nginx ports: - "80:80" links: - app:app db: image: postgres:9.4.1 ports: - "5432:5432" environment: - POSTGRES_PASSWORD=password volumes: - /home/user/pgdata/etc:/etc/postgresql - /home/user/pgdata/log:/var/log/postgresql - /home/user/pgdata/lib:/var/lib/postgresql app: build: . command: bin/rails server --port 3000 --binding 0.0.0.0 links: - db volumes: - .:/my-rails-app volumes_from: - bundle ports: - "3000" bundle: image: ubuntu volumes: - /home/user/volumes/appbundle:/bundle
webserver- Nginx Container configuration. Its going to expose port 80
db – Database PostgreSQL Container configuration. Its going to expose port 5432
app – Rails application configuration. Its going to start webrick server on port 3000.
Note the db volumes, it will share the postgres data with host machine, so that data will be persist even after re-create the container.
Find the container environment variables.
docker-compose run app env
This will list all environment variables. Database host has to be copied to database.yml. Update database.yml
development: adapter: postgresql encoding: unicode database: demo_db01 username: postgres password: postgres pool: 5 host: <%= ENV['DB_1_PORT_5432_TCP_ADDR'] %>
Build and Run the Container
Done with configuration. Lets build and run the container.
docker-compose build docker-compose up
Navigate to http://localhost to see you the application home page. DB migration tasks can be run inside the app container. Lets connect with app container.
docker-compose run app bash rake db:migrate
Thanks for reading. 🙂