Skip to content

Instantly share code, notes, and snippets.

@osulyanov
Forked from palkan/01_readme.md
Last active December 3, 2017 04:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save osulyanov/e13a65dfe5503cb1f4c648b851567c93 to your computer and use it in GitHub Desktop.
Save osulyanov/e13a65dfe5503cb1f4c648b851567c93 to your computer and use it in GitHub Desktop.
Docker Dev

Installation

Go to the official website and choose your OS.

MacOS

Docker for Mac has a problem is the disk IO performance (see docker/for-mac#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:

  1. Update docker File Sharing preferences as explained at https://github.com/IFSight/d4m-nfs (i.e. only /tmp directory should remain)

  2. Quit Docker

  3. Clone repo:

git clone https://github.com/IFSight/d4m-nfs ~/d4m-nfs
  1. Put the following configuration in ~/d4m-nfs/etc/d4m-nfs-mounts.txt:
/Users:/Users
/Volumes:/Volumes
/private:/private
  1. Run the script:
~/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.

File Watchers

D4M-NFS doesn't support FS events, but there are the workarounds for popular text editors (instructions).

Usage

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.

Using multiple configs

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

Useful Aliases

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 Dev Server Configration

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
# 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:
# 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
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"]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment