How to automatically deploy Ruby on Rails in Docker: dockerrails
Basic Rails Applications
Now let's start a basic Rails application. For better display, I use Ruby 2.2.0 and Rails 4.1.1.
Run on the terminal:
$ rvm use 2.2.0 $ rails new && cd docker-test
Create a basic controller:
$ rails g controller welcome index
......, Then edit routes. rb so that the root of the project points to the newly created welcome # index method:
root 'welcome#index'
Run rails s on the terminal, open the browser, and log on to http: // localhost: 3000. You will enter the index interface. We don't want to add amazing things to the application. This is just a basic instance. When we are about to create and deploy a container, use it to verify that everything is running normally.
Install webserver
We plan to use Unicorn as our webserver. Add the gem 'unicorn' and gem 'foreman 'to Gemfile and bundle it (run the bundle install command ).
When starting a Rails application, you need to configure Unicorn first. Therefore, we put a unicorn. rb file in the config directory. Here is an example of the Unicorn configuration file. You can copy and paste the content of Gist directly.
Next, add a Procfile under the root directory of the project so that you can use foreman to start the application. The content is as follows:
Copy codeThe Code is as follows: web: bundle exec unicorn-p $ PORT-c./config/unicorn. rb
Now run the foreman start command to start the application. Everything will run normally and you will be able to see a running application on http: // localhost: 5000.
Build a Docker Image
Now we build an image to run our application. In the root directory of this Rails project, create a file named Dockerfile and paste it into the following content:
Copy codeThe Code is as follows: # image-based ruby 2.2.0
FROM ruby: 2.2.0
# Install required libraries and dependencies
RUN apt-get update & apt-get install-qy nodejs postgresql-client sqlite3 -- no-install-recommends & rm-rf/var/lib/apt/lists /*
# Set the Rails version
ENV RAILS_VERSION 4.1.1
# Installing Rails
RUN gem install rails -- version "$ RAILS_VERSION"
# Create a directory for running the code
RUN mkdir-p/usr/src/app
WORKDIR/usr/src/app
# Enable webserver to be accessed outside the container
EXPOSE 3000
# Setting Environment Variables
Env port = 3000
# Start a web application
CMD ["foreman", "start"]
# Install the required gems
ADD Gemfile/usr/src/app/Gemfile
ADD Gemfile. lock/usr/src/app/Gemfile. lock
RUN bundle install -- without development test
# Add a rails Project (same directory as Dockerfile) to the project directory
ADD. // usr/src/app
# Run a rake task
RUN RAILS_ENV = production rake db: create db: migrate
Run the following command to create an image (ensure that boot2docker is started and running) using the Dockerfile ):
$ docker build -t localhost:5000/your_username/docker-test .
Then, if everything is normal, the last line of long log output should be similar:
Successfully built 82e48769506c $ docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE localhost:5000/your_username/docker-test latest 82e48769506c About a minute ago 884.2 MB
Let's run the container and try it!
$ docker run -d -p 3000:3000 --name docker-test localhost:5000/your_username/docker-test
Through port 3000 of your boot2docker Virtual Machine (my port is http: // 192.168.59.103: 3000), you can observe your Rails application. (If you do not know your boot2docker virtual address, enter the $ boot2docker ip command .)
Use shell scripts for automated deployment
The previous article (articles 1 and 2) tells you how to push a newly created image to a private registry and deploy it on the server, so we skip this part and start the automation process directly.
We will define three shell scripts and then use rake to bundle them together.
Clear
When we create an image,
- Stop and restart boot2docker;
- Remove Docker orphan images (images without tags and no longer used by containers ).
Enter the following command in the clean. sh file under your project root directory.
Copy codeThe Code is as follows: echo Restarting boot2docker...
Boot2docker down
Boot2docker up
Echo Exporting Docker variables...
Sleep 1
Export DOCKER_HOST = tcp: // 192.168.59.103: 2376
Export DOCKER_CERT_PATH =/Users/user/. boot2docker/certs/boot2docker-vm
Export DOCKER_TLS_VERIFY = 1
Sleep 1
Echo Removing orphaned images without tags...
Docker images | grep "<none>" | awk '{print $3}' | xargs docker rmi
Add the execution permission to the script:
$ chmod +x clean.sh
Build
The building process is basically similar to what we have previously done (docker build. Create a build. sh script under the root directory of the project and fill in the following content:
Copy codeThe Code is as follows: docker build-t localhost: 5000/your_username/docker-test.
Remember to grant the script execution permission.
Deployment
Finally, create a deploy. sh script and enter the following content in it:
Copy codeThe Code is as follows: # enable SSH connection from boot2docker to private registry
Boot2docker ssh "ssh-o 'stricthostkeychecking no'-I/Users/username/. ssh/id_boot2docker-N-L 5000: localhost: 5000 root@your-registry.com &"&
# Make sure that the SSH channel is open before pushing.
Echo Waiting 5 seconds before pushing image.
Echo 5...
Sleep 1
Echo 4...
Sleep 1
Echo 3...
Sleep 1
Echo 2...
Sleep 1
Echo 1...
Sleep 1
# Push image onto remote registry/repo
Echo Starting push!
Docker push localhost: 5000/username/docker-test
If you do not understand the meaning, read the second part carefully.
Add the execution permission to the script.
Use rake to bind all the above
Now, every time you want to deploy your application, you need to run these three scripts separately.
- Clean
- Build
- Deploy/push
This is not a waste of time, but in fact developers are much less than you think! So we just need to be more lazy!
Finally, let's sort out our work. Now we need to bind three scripts together through rake.
To make it easier, you can add several lines of code to the Rakefile that already exists in the project root directory, open the Rakefile file, and paste the following content into it.
namespace :docker do desc "Remove docker container" task :clean do sh './clean.sh' end desc "Build Docker image" task :build => [:clean] do sh './build.sh' end desc "Deploy Docker image" task :deploy => [:build] do sh './deploy.sh' end end
Even if you don't know the rake syntax (you should know about it, it's so cool !), The above content is also clear. We declare three tasks in a namespace (docker.
The three tasks are:
- Rake docker: clean
- Rake docker: build
- Rake docker: deploy
Deploy is independent of build and build is independent of clean. So every time we enter a command to run it.
$ rake docker:deploy
All scripts are executed in sequence.
Test
Now let's see if everything is normal. You just need to make a small change in the app code:
$ rake docker:deploy
The next step is to witness the miracle. Once the image file is uploaded (it may take a long time for the first time), you can log on to the product server by using ssh and pull the docker image to the server and run it. How simple!
You may need to get used to it for a while, but once it succeeds, it is almost as simple as deploying it with Heroku.
Note: As usual, please let me know your opinions. I cannot guarantee that this method is the best, fastest, or safest method for Docker development, but it does work for us.