I have simple rails application with docker-compose.yml file.
It consists from two containers - db container with PostgreSQL and web container with rails app.
In dockerfile for web part I have such lines in CMD
CMD RAILS_ENV=production rake db:create db:migrate && \
bundle exec rails s -p 3000 -b '0.0.0.0' --environment=production
So in line rake db:create db:migrate I create db if it is a first run of db container, and run migrate.
But if it is only update of web part - I need only to run db:migrate, and db:create (as it should) give me error
ERROR: database "myapp_production" already exists
STATEMENT: CREATE DATABASE "myapp_production" ENCODING = 'unicode'
Everything working fine, but I think there is a better way.
What is a best way to handle this situation?
I have the same development stack and here is that I'm doing.
Here is a Dockerfile for postgres which I'm extend:
FROM postgres:9.4
ADD db/init.sql /docker-entrypoint-initdb.d/
EXPOSE 5432
CMD ["postgres"]
From the docker postgres documentation:
If you would like to do additional initialization in an image derived from this one, add one or more
*.sqlor*.shscripts under/docker-entrypoint-initdb.d(creating the directory if necessary). After the entrypoint callsinitdbto create the default postgres user and database, it will run any*.sqlfiles and source any*.shscripts found in that directory to do further initialization before starting the service.
My init.sql:
CREATE USER database_user;
CREATE DATABASE database_production;
GRANT ALL PRIVILEGES ON DATABASE database_production TO database_user;
After that my RUN command in the web container points to the run.sh script:
#!/usr/bin/env bash
echo "Bundling gems"
bundle install --jobs 8 --retry 3
echo "Clearing logs"
bin/rake log:clear
echo "Run migrations"
bundle exec rake db:migrate
echo "Seed database"
bundle exec rake db:seed
echo "Removing contents of tmp dirs"
bin/rake tmp:clear
echo "Starting app server ..."
bundle exec rails s -p 3000 -b '0.0.0.0'
That's it. My database created in the db container, and web app only does migration.