class: center, middle # Docker Workshop
What's under the Hood? [Fitter](https://www.youtube.com/watch?v=hs64rB0cLNw). [Happier](https://www.youtube.com/watch?v=My10FLH5DT0). [More productive](https://www.youtube.com/watch?v=9ORllD7fA6I).
Presented by *Michael Herman*
--- ### Agenda -- ##### (1) About Me -- ##### (2) Objectives -- ##### (3) Theory 1. What is Docker? 1. Install Docker 1. Concepts -- ##### (4) Practice 1. Dockerfile Basics 1. Build an Image 1. Run the Image 1. Docker Compose Basics 1. Database Service 1. Node Service 1. Build and Run 1. Workflow -- ##### (5) Next Steps --- ## About Michael ``` $ whoami michael.herman ``` -- #### Day Job: - Software Engineer at [ClickFox](https://www.clickfox.com/) as of October 2017 - Instructor and Software Enginner at [Galvanize](http://www.galvanize.com/) from May 2015 to September 2017 -- #### Also: - Co-founder/author of [Real Python](https://realpython.com) - 😍 - [tech writing](http://mherman.org), [open source](http://github.com/mjhea0), [financial models](http://www.starterfinancialmodel.com/), [radiohead](http://radiohead.com/), [chilling](images/me.jpg)
--- ### Objectives By the end of this talk, you should be able to: 1. Describe what Docker is and why it's useful 1. Describe the relationship between a Dockerfile, image, and container 1. Simplify your development workflow with Docker Compose 1. Install Docker Community Edition for Mac 1. Build an image from a Dockerfile 1. Create a container from an image 1. Work with a Node app running inside a container 1. Pass environment variables to a running container 1. Utilize volumes to mount code into a container -- *4 through 9 are applicable only if you brought your computer along `&&` are coding along.* --- ### What is Docker? -- [Docker](https://www.docker.com/) is a containerization tool used for spinning up isolated, reproducible application environments. -- 1. **Lightweight** - uses the host computer's processes (check out [Containers are not VMs](https://blog.docker.com/2016/03/containers-are-not-vms/)) 1. **VCS** - Version control system for infrastructure 1. **Distribution** - Easily distribute and recreate your entire development environment 1. **Build once, run anywhere** (aka, The Holy Grail!) - no more environment-specific bugs
--- ### Install Docker https://www.docker.com/community-edition ```sh $ docker -v Docker version 17.06.2-ce, build cec0b72 ``` -- Obligatory 'Hello, World': ```sh $ docker run hello-world ```
--- ### Concepts https://docs.docker.com/engine/docker-overview/ - **[Dockerfiles](https://docs.docker.com/glossary/?term=Dockerfile)** - scripts with a set of instructions used to create an *image*. -- - **[Images](https://docs.docker.com/glossary/?term=image)** - are used to build and save snapshots (the state) of an environment. It's blueprint for a *container*. > **NOTE:** You can think of an image as a virtual operating system, but smaller and more efficient. -- - **[Container](https://docs.docker.com/glossary/?term=container)** is an instantiated, live *image* that runs a collection of processes.
--- ### Dockerfile Basics https://github.com/mjhea0/docker-workshop/blob/master/locations/Dockerfile: ```sh FROM node:latest # set working directory RUN mkdir /usr/src/app WORKDIR /usr/src # add `/usr/src/node_modules/.bin` to $PATH ENV PATH /usr/src/node_modules/.bin:$PATH # install and cache app dependencies ADD package.json /usr/src/package.json RUN npm install # add files and folders to the container ADD /app /usr/src/app # start app CMD ["npm", "start"] ``` -- Be sure to take advantage of Docker’s layered [caching](https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/#build-cache) system, to speed up build times, by adding the *package.json* and installing the dependencies **before** adding the app’s source files. --- ### Build an Image Within the "locations" directory, run: ```sh $ docker build -t "locations" . ``` -- **What's happening?** Docker pulls down the base [Node](https://hub.docker.com/_/node/) image found on [Docker Hub](https://hub.docker.com/), an [image registry](https://docs.docker.com/registry/) (it's like GitHub for Docker Images). From there, each line, called a [layer](https://docs.docker.com/glossary/?term=layer), from the Dockerfile is run and added to the new image. > **NOTE:** The first time you build an image, it will take some time. Subsequent builds should be *much* faster since layers are cached locally - only layers that change will be updated. -- Run `docker images` to view the newly created image. -- You can also add a version to the tag name: ```sh $ docker build -t "locations:v2" . ``` --- ### Run the Image To run the `locations` image: ```sh $ docker run -d -p 80:1337 locations ``` - `-p` connects port 1337 of the Docker container to port 80 of your machine - `-d` runs the container in the background > **NOTE:** Instead of localhost (127.0.0.1), this could also be the IP associated with Docker Machine - `docker-machine ip MACHINE_NAME`. -- Helpful commands for running containers: 1. View: `docker ps` 1. Stop: `docker stop CONTAINER_ID` 1. View the logs: `docker logs CONTAINER_ID -f` 1. Enter bash: `docker exec -it CONTAINER_ID bash` 1. Run tests: `docker exec -it CONTAINER_ID npm test` -- To pass an environment variable at run-time: ```sh $ docker run -d -p 80:1338 -e PORT=1338 locations ``` --- ### Docker Compose Basics https://github.com/mjhea0/docker-workshop/blob/master/locations-db/docker-compose.yml -- This file is used by [Docker Compose](https://docs.docker.com/compose/) to link multiple services together. With one command it will spin up the defined services and enable them to communicate with one another. https://stackoverflow.com/questions/37966552/what-is-the-difference-between-docker-and-docker-compose
--- ### Database Service From *docker-compose.yml* within "locations-db": ```yaml locations-db: container_name: locations-db build: ./app/db ports: - '5433:5432' environment: - POSTGRES_USER=admin - POSTGRES_PASSWORD=admin healthcheck: test: exit 0 ``` Here, we create a new container called `locations-db`, from the Dockerfile found in "locations-db/app/db". We also add environment variables, expose ports, and send an exit code of `0` once it is successfully up and running - which will be used by other services. --- ### Node Service From *docker-compose.yml*: ```yaml locations-service: container_name: locations-service build: . volumes: - './app:/usr/src/app' - './package.json:/usr/src/package.json' - './knexfile.js:/usr/src/knexfile.js' ports: - '1337:1337' environment: - DATABASE_URL=postgres://admin:admin@locations-db:5432/locations_dev - DATABASE_TEST_URL=postgres://admin:admin@locations-db:5432/locations_test - NODE_ENV=development depends_on: locations-db: condition: service_healthy links: - locations-db ``` **What’s new here?** 1. [volumes](https://docs.docker.com/engine/tutorials/dockervolumes/) - mount directories into a container so that you can make changes to the code without having to build a new image. 1. [depends_on](https://docs.docker.com/compose/compose-file/#depends_on) - used to start services in a specific order. 1. [links](https://docs.docker.com/compose/compose-file/#links) - connect services together. --- ### Build and Run Build the images: ```sh $ docker-compose build ``` Run the containers: ```sh $ docker-compose up -d ``` Migrate and seed: ```sh $ docker-compose run locations-service knex migrate:latest \ --env development --knexfile knexfile.js $ docker-compose run locations-service knex seed:run \ --env development --knexfile knexfile.js ``` Test: ```sh $ docker-compose run locations-service npm test ``` --- ### Workflow Some commands... **Check env variables:** ```sh $ docker-compose run locations-service env ``` **Force new build**: ```sh $ docker-compose build --no-cache ``` **Stop running containers**: ```sh $ docker-compose stop ``` **Enter psql**: ```sh $ docker exec -ti locations-db psql -U admin -W ``` --- ### That's it! What's next? -- **Resources**: 1. [Slides](http://mherman.org/docker-workshop) 1. [Project Repo](https://github.com/mjhea0/docker-workshop) 1. [How to Build 12 Factor Microservices on Docker](https://www.packtpub.com/books/content/how-to-build-12-factor-design-microservices-on-docker-part-1) 1. [Docker Cheat Sheet](https://github.com/wsargent/docker-cheat-sheet) 1. [Play with Docker](http://training.play-with-docker.com/) 1. [Learn Docker in 12 Minutes](https://www.youtube.com/watch?v=YFl2mCHdv24]) (video) -- **Bigger examples**: 1. [Developing and Testing Microservices With Docker](http://mherman.org/blog/2017/04/18/developing-and-testing-microservices-with-docker) 1. [Developing Microservices - Node, React, and Docker](http://mherman.org/blog/2017/05/11/developing-microservices-node-react-docker) 1. [Microservices with Docker, Flask, and React](http://testdriven.io/) - *[testdriven.io](http://testdriven.io/)* 1. [Developing React with Docker](http://mherman.org/node-workshop/slides/react-docker) -- Questions?