├── new ├── hello.py ├── index.js ├── Dockerfile ├── docker-compose.yml └── README.md /new: -------------------------------------------------------------------------------- 1 | hello you 2 | -------------------------------------------------------------------------------- /hello.py: -------------------------------------------------------------------------------- 1 | print("Hello") 2 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | console.log("hi"); 2 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine 2 | CMD ["ping", "google.com"] 3 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "2" 2 | 3 | services: 4 | ping: 5 | image: pinger 6 | pong: 7 | image: pinger 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Getting Started With Docker 2 | 3 | ## Installing Docker 4 | 5 | Befoe beginning, please follow the [installation instructions](https://docs.docker.com/engine/installation/) provided for your OS by Docker. 6 | 7 | ## Conceptual Overview of Docker 8 | 9 | While not necessary to complete these exercises, you might find it interesting or helpful to read up on the largely conceptual [Docker Overview](https://docs.docker.com/engine/understanding-docker/). 10 | 11 | ## Running Commands in a Container 12 | 13 | *Containers* are run from *images* on a host machine using the following syntax: 14 | 15 | `docker run [OPTIONS] IMAGE [COMMAND] [ARG...]` 16 | 17 | You can see what images exist on the host machine with `docker images`. If the image you are wanting to run from does not exist locally, Docker will attempt to pull it down from [DockerHub](https://hub.docker.com/). 18 | 19 | You can see what containers are running on the host machine with `docker ps`. You can see all containers on a host machine, running and stopped, with `docker ps -a`. 20 | 21 | - [ ] Look at what images, if any, are currently stored on the host machine you are using 22 | - [ ] Run a container using the `alpine` image, issuing the command `echo hello world` 23 | - [ ] Look again at what images are currently stored on the host machine 24 | - [ ] Observe if there are any running or any stopped containers on the host machine 25 | - [ ] Run a container using the `alpine` image that uses `pwd` to print the default directory inside the container 26 | - [ ] Run a container using the `alpine` image that uses `ls` to observe the contents of the default directory inside the container 27 | - [ ] Run a container using the `alpine` image that uses `cat` to observe the contents of the `/etc/hosts` file inside the container 28 | 29 | When you want to issue commands that require piping or redirection, you should use the `sh -c ""` syntax rather than issuing commands directory. 30 | 31 | - [ ] Run a container using the `alpine` image that uses `grep` to print the lines of `/etc/hosts` containing `127` 32 | 33 | ## Provisioning a TTY to Interact Inside a Container 34 | 35 | Using the options `-i` and `-t`, you can provision an **i**nteractive **T**TY. Used in conjunction with a command that results in a command line, such as `sh` (which you can expect to be available on most all containers) or `bash`, or `python` or `node` or `redis-cli` or `mongo`, you can interact with the command line inside of a container. 36 | 37 | - [ ] Run a container using the `alpine` image that provisions an interactive TTY and invokes the `sh` command 38 | 39 | ## Container Cleanup 40 | 41 | You might notice (using `docker ps -a`) that containers are starting to pile up. You can remove containers with `docker rm [CONTAINER-NAME-OR-ID]`. To remove stopped containers in mass consider the one-liner `docker rm $(docker ps -aq)` 42 | 43 | - [ ] Clean up your stopped containers, first one at a time and then in mass 44 | 45 | ## Committing Modified Containers to Build a New Image 46 | 47 | While containers are run from images, new images are built by taking snapshots of a given container. When you make modifications inside of a container, you can *commit* those changes to a new image using the syntax `docker commit [CONTAINER-NAME-OR-ID] [NEW-IMAGE-TAG]`. Also, when running a container, you can use the `--name [NAME]` option to give the container a name of your choosing, rather than Docker's randomly generated one. 48 | 49 | - [ ] Run a container from the `alpine` image that uses `touch` to create a new file within it. Give the container the name `modified` 50 | - [ ] Commit the `modified` container to a new image called `my-new-image`. Confirm the image is now present on your host machine 51 | - [ ] Run a container from the `my-new-image` image that issues a command confirming the file you `touch`ed exists 52 | 53 | ## Running a Persistent Command Inside a Container 54 | 55 | Docker containers will stop as soon as the command that was issued within them completes. So far all the commands we have issued have been one off commands. By issuing a persistent command, the container will continue to run. Often when running containers with persistent commands, you'll want to use the `-d` flag to run it in the background. 56 | 57 | You can look at the logs for a running or stopped container with `docker logs [CONTAINER]`. To follow the logs of a container add the `-f` flag. 58 | 59 | - [ ] Run a command from the `alpine` image, in the background, with the name `pinger`, that uses `ping google.com` as its command 60 | - [ ] Confirm that the container is running 61 | - [ ] Look at the logs for the `pinger` container 62 | - [ ] Follow the logs for the `pinger` container 63 | 64 | ## Issuing Commands in a Running Container 65 | 66 | Especially with running containers, you might wish to execute a command within it while it is running. This is done with `docker exec [OPTIONS] CONTAINER COMMAND [ARGS]` 67 | 68 | - [ ] Issue a one off command inside your running `pinger` container, such as `uname` 69 | 70 | ## Stopping and Removing a Running Container 71 | 72 | Before you can remove a running container you must stop it with `docker stop CONTAINER`. Alternatively you can pass the `-f` flag into `docker rm`. 73 | 74 | - [ ] Stop and remove the `pinger` container 75 | 76 | ## Building a New Image With a Dockerfile 77 | 78 | Typically, we build new images by leaving instructions for building them within a special file called `Dockerfile`, which always contains instructions for an image to build this new image `FROM`, and then often, a default `CMD` for a container run from this new image to use. Once we have a `Dockerfile`, we build a new image with `docker build -t IMAGE-TAG PATH-TO-DOCKERFILE` 79 | 80 | You will use the following contents for a `Dockerfile`. 81 | ``` 82 | FROM alpine 83 | CMD ["ping", "google.com"] 84 | ``` 85 | 86 | - [ ] Using this `Dockerfile`, `build` a new image with the tag `pinger`. 87 | - [ ] Run a container named `my-pinger` using the newly built `pinger` image. You do not need to issue a command since the `Dockerfile` for `pinger` gave a default 88 | - [ ] Confirm your container is running. Look at its logs and then clean it up. 89 | - [ ] Remove the newly built `pinger` image using `docker rmi IMAGE` 90 | 91 | ## Building an Image With Application Code 92 | 93 | Typically you'll want to build a new image that contains application code. Write the following python script, which you will be building into an image: 94 | 95 | hello.py 96 | ``` 97 | print("hello") 98 | ``` 99 | 100 | In order to run python code inside a container, we should build our images with an image that already has python installed. 101 | 102 | - [ ] Interact with a python interpreter inside a container with python installed by issuing `docker run -it jfloff/alpine-python:3.4 python` 103 | 104 | In order to house our application code inside an image we will modify the Dockerfile with instructions for placing our application code within the image we are building. 105 | 106 | Dockerfile 107 | ``` 108 | FROM python:3.5 109 | RUN mkdir app 110 | ADD hello.py /app 111 | WORKDIR /app 112 | CMD ["python", "hello.py"] 113 | ``` 114 | 115 | docker build -t hello-py . 116 | docker run hello-py 117 | [change the file, rebuild and run] 118 | 119 | ## Mounting a Volume Into a Container 120 | 121 | docker run -v $PWD:/app h ello-py 122 | [change the file and run] 123 | 124 | ## Using Docker Compose to Build and Image and Run a Container 125 | 126 | docker-compose.yml 127 | ``` 128 | version: "2" 129 | 130 | services: 131 | greeter: 132 | build: . 133 | `` 134 | 135 | docker-compose up 136 | 137 | docker-compose.yml 138 | ``` 139 | version: "2" 140 | 141 | services: 142 | greeter: 143 | build: . 144 | volumes: 145 | - ./:/app 146 | ``` 147 | 148 | ## Communicating Between Containers Using Docker Compose 149 | 150 | docker-compose.yml 151 | ``` 152 | version: "2" 153 | 154 | services: 155 | ping: 156 | image: pinger 157 | pong: 158 | image: pinger 159 | ``` 160 | 161 | docker-compose up -d 162 | docker ps 163 | docker-compose logs -f 164 | 165 | docker exec -it sh 166 | ping pong 167 | --------------------------------------------------------------------------------