# Docker ## Getting our App Get zip file ## Building the App's Container Image ```docker FROM node:12-alpine RUN apk add --no-cache python g++ make WORKDIR /app COPY . . RUN yarn install --production CMD ["node", "src/index.js"] ``` ```bash docker build -t getting-started . ``` ## Starting an App Container ```bash docker run -dp 3000:3000 getting-started ``` After a few seconds, open your web browser to `http://localhost:3000`. You should see our app! ## Create a Repo - Go to Docker Hub and log in if you need to. - Click the Create Repository button. - For the repo name, use getting-started. Make sure the Visibility is Public. - Click the Create button! ## Pushing our Image - Login to the Docker Hub ```bash docker login -u YOUR-USER-NAME ``` - Use the docker tag command to give the getting-started image a new name. Be sure to swap out YOUR-USER-NAME with your Docker ID. ```bash docker tag getting-started YOUR-USER-NAME/getting-started ``` - Now try the push command. If you're copying the value from Docker Hub, you can drop the tagname portion, as we didn't add a tag to the image name. If you don't specify a tag, Docker will use a tag called latest. ```bash docker push YOUR-USER-NAME/getting-started ``` ## Persisting our Todo Data - Create a volume by using the docker volume create command. ```bash docker volume create todo-db ``` - Start the todo app container, but add the -v flag to specify a volume mount. We will use the named volume and mount it to /etc/todos, which will capture all files created at the path. ```bash docker run -dp 3000:3000 -v todo-db:/etc/todos getting-started ``` ## Diving into our Volume A lot of people frequently ask "Where is Docker actually storing my data when I use a named volume?" If you want to know, you can use the docker volume inspect command. ```js docker volume inspect todo-db [ { "CreatedAt": "2019-09-26T02:18:36Z", "Driver": "local", "Labels": {}, "Mountpoint": "/var/lib/docker/volumes/todo-db/_data", "Name": "todo-db", "Options": {}, "Scope": "local" } ] ``` The Mountpoint is the actual location on the disk where the data is stored. Note that on most machines, you will need to have root access to access this directory from the host. But, that's where it is! ## Starting a Dev-Mode Container To run our container to support a development workflow, we will do the following: - Mount our source code into the container - Install all dependencies, including the "dev" dependencies - Start nodemon to watch for filesystem changes So, let's do it! 1. Make sure you don't have any previous getting-started containers running. 2. Run the following command. We'll explain what's going on afterwards: ```bs docker run -dp 3000:3000 \ -w /app -v "$(pwd):/app" \ node:12-alpine \ sh -c "yarn install && yarn run dev" ``` If you are using PowerShell then use this command. ```bs docker run -dp 3000:3000 ` -w /app -v "$(pwd):/app" ` node:12-alpine ` sh -c "yarn install && yarn run dev" ``` - -dp 3000:3000 - same as before. Run in detached (background) mode and create a port mapping - -w /app - sets the "working directory" or the current directory that the command will run from - -v "$(pwd):/app" - bind mount the current directory from the host in the container into the /app directory - node:12-alpine - the image to use. Note that this is the base image for our app from the Dockerfile - sh -c "yarn install && yarn run dev" - the command. We're starting a shell using sh (alpine doesn't have bash) and running yarn install to install all dependencies and then running yarn run dev. If we look in the package.json, we'll see that the dev script is starting nodemon. 3. You can watch the logs using docker logs -f \. You'll know you're ready to go when you see this... ```bs docker logs -f $ nodemon src/index.js [nodemon] 1.19.2 [nodemon] to restart at any time, enter `rs` [nodemon] watching dir(s): *.* [nodemon] starting `node src/index.js` Using sqlite database at /etc/todos/todo.db Listening on port 3000 ``` When you're done watching the logs, exit out by hitting Ctrl+C.