In this video, learn how to set up the tools required to build and run the project. Docker and Docker Compose are your friends for this step.
- [Instructor] In order to get any work done on your inherited project, you need to set up a development environment. On many projects this can be particularly challenging. Documentation can be missing. Tools can be outdated or hard to install, or might not even be available for the operating system that you're running it on. Numerous third-party libraries may be needed. On some projects, sorting out all of these details can take days or weeks, and this time can be additionally stressful because it's nearly impossible to predict how long it's going to take to sort through it all. This makes it very difficult to set expectations for people who are waiting for improvements to the system that you're working on. Worse still, if another team member joins your project, they are likely to have all of the same problems. So it's important to capture everything that you learn in a way that can be repeated in the future. And when you have to replace your work station that information will come in handy even if you don't add another team member. On many projects, Docker and Docker Compose are the perfect technologies to help address these issues. Many teams discount using Docker for their development environment because they have no plans to use it in production. However, these tools can yield impressive benefits, even on projects that will never use Docker in production. Let's take a peek at what's required to use Docker and Docker Compose to work on an old Ruby project. Here we're working with version 1.0 of the Sinatra project which was released in March of 2010. Our goal is to be able to run the test suite without any failures and without having to change any of the library's code. To do that we're using Docker and Docker Compose to construct a development environment that is very similar to what a developer might have used when the code was released. This was prepared ahead of time. But let's walk through everything that was done. We'll start by looking at the Dockerfile. The first line of this file is a FROM statement which specifies the Docker image to use as a starting point. Here, we're using a community-provided image, which is designed to allow active development on projects that require using Ruby 1.9.3. which was the Ruby version available at around the time the code that we're working on was released. Other than specifying a Ruby version to use, the rest of this file just ensures that an app directory is created for us to work with. Let's peek at the docker-compose.yaml file. The first line specifies the version of the file format we're working with. The services section is where we specify any services that are needed to run the app that we're working on. Here we only have one service, but if we were working with a database, we'd add a service for launching the database engine. We're specifying that the app service should be built using the Dockerfile in the same directory as the docker-compose.yaml file. The next line down specifies a script to run each time the container starts. Next is the volume configuration. We mirror the current source directory inside the container as the app directory. And the rest of this file configures caches which will be used to install any Ruby gems by bundler. This will ensure that they don't need to be installed every time the app container starts. Now let's take a peek at the docker-entrypoint.sh file which runs each time the app container is started. This script simply checks to see if the dependencies have been installed and if not, goes ahead and installs them. Now we can get a command line shell inside of our development environment by running docker-compose run app bash. The very first time that this command is run it'll build a docker image using the details that we specified in the Dockerfile. And then it'll start the container and run the entrypoint script which installs all of the gems first. Once all the gems are installed we'll have a command shell inside of an isolated development environment for our application. And if we want to make any changes to how the environment is built we just need to alter the Dockerfile. This creates a form of documentation for our development environment which is executable. And now we can run the test suite and see that everything is passing. One final note, in order to get those tests passing, I had to add extra restrictions on the version numbers that this library is depending on. I limited the dependencies to ones that were released at around the same time that this code was. Before doing this, almost all of the tests were failing. This exercise is pretty representative of how to use Docker and Docker Compose for creating a development environment for an older project. And now that there's an isolated container to work within, it will be easier to make improvements to the project.
- Assessing the technical debt
- Creating and running a test suite
- Handling failing tests
- Updating dependencies and tools
- Paying down technical debt
- Remaining test driven
- Monitoring code quality