Docker Dev
FROM ruby:2.4
# PostgreSQL utils
# This is required if you use SQL format for your schema (then you need psql)
ENV PG_MAJOR 9.5
RUN echo 'deb http://apt.postgresql.org/pub/repos/apt/ jessie-pgdg main' $PG_MAJOR > /etc/apt/sources.list.d/pgdg.list
RUN wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add -
RUN apt-get update && apt-get install -y build-essential
RUN apt-get install -y libpq-dev apt-utils postgresql-client-$PG_MAJOR
# Node installation
RUN curl -sL https://deb.nodesource.com/setup_6.x | bash -
RUN apt-get install -y nodejs
RUN mkdir -p /app
WORKDIR /app
ENV LANG C.UTF-8
ENV BUNDLE_PATH /bundle
ENV BUNDLE_BIN /bundle/bin
ENV PATH /app/bin:/bundle/bin:$PATH
RUN gem install bundler
EXPOSE 3000
ENTRYPOINT ["bundle", "exec"]
CMD ["rails", "server", "-b", "0.0.0.0"]
# Example docker-compose for a sub-service
version: '3'
services:
# If you have another app and want to share
# some resources
another_app:
build:
# path to another app root (and Dockerfile)
context: '../another-app'
image: another-app:1.1
command: bundle exec sidekiq
environment:
- REDIS_URL=redis://redis:6379/
volumes:
- ../another-app:/app
# Here we use services and volumes defined in the main config
- bundle:/bundle
depends_on:
- redis
# Example docker-compose for a typical Rails+Webpack application
version: '3'
services:
app: &app
build: .
# Update version every time your Dockerfile changes
image: my_app:1.0
volumes:
- .:/app
backend: &backend
<<: *app
volumes:
- .:/app
# Persist installed gems
- bundle:/bundle
environment:
- REDIS_URL=redis://redis:6379/
- DATABASE_URL=postgres://postgres:postgres@postgres:5432
- ES_HOST=es
- WEBPACK_URL=http://localhost:3100
depends_on:
- postgres
- es
- redis
web:
<<: *backend
command: rails server -b 0.0.0.0
ports:
# Container:Host
- '3000:3000'
sidekiq:
<<: *backend
command: sidekiq -C config/sidekiq.dev.yml
runner:
<<: *backend
entrypoint: /bin/bash
webpack:
<<: *app
entrypoint: /bin/bash
command: -c 'npm run webpack:development -- --host 0.0.0.0'
ports:
- '3100:3100'
postgres:
image: postgres:9.5
volumes:
# Persist postgres data
- postgres:/var/lib/postgresql/data
ports:
- 5432
es:
image: elasticsearch:2.2
volumes:
# Persist elastic data
- es:/usr/share/elasticsearch/data
ports:
- 9200
- 9300
redis:
image: redis:3.2-alpine
volumes:
# Persist Redis data
- redis:/data
ports:
- 6379
volumes:
postgres:
es:
redis:
bundle:
Go to the official website and choose your OS.
Docker for Mac has a problem is the disk IO performance (see https://github.com/docker/for-mac/issues/77).
There is a fix (https://github.com/IFSight/d4m-nfs) which makes Docker use NFS instead of OSXFS.
NOTE: MacOS High Sierra <10.3.2 is likely to have problems with NFS (see discussion).
Follow the instructions:
Update docker File Sharing preferences as explained at https://github.com/IFSight/d4m-nfs (i.e. only /tmp
directory should remain)
Quit Docker
Clone repo:
git clone https://github.com/IFSight/d4m-nfs ~/d4m-nfs
~/d4m-nfs/etc/d4m-nfs-mounts.txt
:/Users:/Users
/Volumes:/Volumes
/private:/private
~/d4m-nfs/d4m-nfs.sh
6*) Optional Add shortcut to run d4m-nfs
:
echo "#\!/usr/bin/env bash\n/Users/`whoami`/d4m-nfs/d4m-nfs.sh" > /usr/local/bin/d4m
chmod +x /usr/local/bin/d4m
And then just run d4m
to start Docker.
NOTE: it requires root access to modify /etc/exports
, /etc/nfs.conf
, etc.
That's it.
NOTE: now you must start Docker using the same script (~/d4m-nfs/d4m-nfs.sh
or d4m
) in order it to work correctly.
D4M-NFS doesn't support FS events, but there are the workarounds for popular text editors (instructions).
Add Dockerfile
to build you application and docker-compose.yml
to configure services (see examples below).
Basic commands:
# build app container
docker-compose build app
# run setup script (bundle install, db:migrate, db:seed)
docker-compose run runner -c ./bin/setup
# setup frontend dependencies
docker-compose run webpack -c 'npm install'
# run web app
docker-compose up web
# run sidekiq
docker-compose up sidekiq
# run the whole app
docker-compose up web webpack sidekiq
# run specs
docker-compose run web rspec
# simply launch bash within app directory
docker-compose run runner
Usually, the runner
container is always running and you're working within it (install gems, run generators, tests, etc).
So, docker-compose run runner
is like vagrant ssh
.
Sometimes it's useful to have separate docker-compose
configurations (e.g. when working with microservices).
You can re-use some services (e.g. databases) by passing several configuration files:
docker-compose -f docker-compose.yml -f docker-compose-service.yml up web webpack sidekiq another_app
alias dcr='docker-compose run --rm'
alias dcu='docker-compose up'
alias dcs='docker-compose stop'
alias dstats='docker stats --format "table {{.Name}}:\t{{.MemUsage}}\t{{.CPUPerc}}"'
Webpack config:
devServer: {
contentBase: paths.dest,
clientLogLevel: 'warning',
disableHostCheck: true,
headers: { 'Access-Control-Allow-Origin': '*' },
inline: true,
overlay: true,
port: 3100,
publicPath: '/front/',
}
Rails helper:
def webpack_bundle_tag(bundle, options = {})
host = Rails.env.development? ? ENV['WEBPACK_URL'] : compute_asset_host
bundle_tag = javascript_include_tag("#{host}/front/#{Webpack.entry_path(bundle)}", options)
if bundle == 'shared' && (manifest = Webpack.manifest)
"#{javascript_tag "window.webpackManifest = #{manifest};"}\n#{bundle_tag}".html_safe
else
bundle_tag
end
end