These instructions will guide you through the first steps to setup a Docker environment on a Mac. From there you will be able to setup your first "hello world" container. The intent is to get you familiar with the commands used to start a container, check its status and stop the container. Please begin by forking this repository to your GitHub account and then cloning the repository to your Mac. Then follow these steps:
- Create a Docker ID
- Visit https://www.docker.com
- Click Create Docker ID and follow the prompts
- Next Install Docker for Mac
- https://docs.docker.com/docker-for-mac/install/
- Click "Get Docker for Mac (Stable)" link and follow the instructions on the website and in the app
- Provide your Docker ID for the app to use while it runs in the background
- Open a terminal in a new Mac desktop that is full screen and let's have fun with Docker commands
- In your terminal type the command
docker search debian | more- note that both ubuntu and debian are listed at the top and that there is an [OK] under the official column. This means these images are the offically blessed images by the ubuntu and debian community.
- Let's choose the debian image for our first exercise and type the command
docker run -ti debian:stretch bash- note how quickly you built a container and it is running. This action pulled an image from the public Docker registry and ran it.
- Now let's check the Linux release of the container by typing
cat /etc/*-release, the version should say 9 (stretch) - Now type
exitto exit the container or press Ctrl D on your keyboard. Either option works. - Let's clean up the container we just created by listing it and removing it, type the command
docker container ps -a- note that
docker container psjust shows running containers and the -a switch says to show all containers running or not
- note that
- Now remove the Docker container by typing
docker rm "container_id"where container_id is the unique identifying number that is given to the Debian container you just ran.- note containers have their own unique ids and images have their own set of unique ids
- Now type the command
docker run --name voldemort debian:stretchthen rundocker container ps -athen remove voldemort from your computer by typingdocker rm voldemort- note wasn't that easier than having to type the container identifier?
In this exercise you will become familiar with the docker commit command which allows you to create a new image from an existing container. This is useful if you have made changes to a container and want to make a new image from it for future use.
- In your terminal type the command
docker run -ti --name ronald debian:stretch bash - Now create a file in this new container by typing
touch ron_was_here.txtand typels- note your file is at the root of your container
- Now exit your container and type
docker container ps -ato note that the ronald container is there but stopped - Now type
docker start ronaldwhich starts up the container - Now type
docker attach ronaldwhich puts you back in the bash shell of the container, typelsto make sure the ron_was_here.txt file is still there then typeexit. - Let's make a new image from the ronald container by typing
docker commit ronald harryand then typedocker commit ronald harry:potter - Type
docker imagesand note that you now see two images one name harry with a tag of latest and another named harry with a tag of potter - Type
docker run -ti --name harry harry:potterand typelsto note that the ron_was_here.txt file is in the new container - Type exit
- Type
docker rmi harry:potter - Type
docker rm harry
Although this example is simple the idea here is to see how you take a container, add new configurations to it and make and image from it to be used in other containers. However, as useful as docker commit is ultimately you will most likely use it rarely and instead will favor the Dockerfile process to build your images. Using docker commit is typically a one time process where you have to create the first container to make the next image. A Dockerfile is a more consistent way to make repeatable images or new images with changes to the Dockerfile options.
In this exercise you will become familiar with running a container that runs a command.
- In your terminal type the command
docker run -ti --name kirk debian apt-get updateand note that apt-get update ran - Type
docker container ps -aand notice the output, you see the kirk container is stopped and that its command was apt-get update - Type
docker rm kirk
The entire point of this quick exercise is to know that docker containers run a single process and when that is done it stops the container afterward.
At this point we have been running containers in a very rudimentary fashion just to get familiar with basic commands. Now we move into building an image with a Dockerfile. You will use the Dockerfile that is already included in this repository under the directory build1 as the starting point.
Change directory or cd build1 into the build1 folder of this repository. Cat or open the Dockerfile to see the contents. Note the structure of the file. The FROM line is always first and says what image to build from, in this case debian:stretch. The first RUN line performs and update and installs curl and pv and the second RUN line runs an echo statement. The CMD line will run the command once the image is run as a container.
- Let's build the image by typing the command
docker build -t spell .- Note the steps of the build process
- Now run the image as a container by typing the command
docker run --rm spell- note the --rm command automatically removes the container once it has completed. This saves the step of running
docker rm spellafter the container is done.
- note the --rm command automatically removes the container once it has completed. This saves the step of running
We will now build a second image with another Dockerfile. Remember that the captial D in the word Dockerfile is a required.
Change directory up one level or cd .. and then change directory again into the build2 folder or cd build2. Cat or open the Dockerfile and see the contents. This time we are pulling an existing nginx image from the Docker public repository. Nginx is a webserver much like Apache.
- Let's build the image from the Dockerfile by typing
docker build -t helloworld .Note the build process and review the output. - Now run the helloworld image as a container by typing
docker run -ti -p 8080:80 --name web1 helloworld- note that I added the -p option which specifies to the external world port 8080 is open and maps to the container's port of 80. Also note that we called this container web1 and built it form the helloworld image we created in step 1.
- Let's go see the results of this container running by opening a browser and typing in the address
localhost:8080. You should see the statement Hello World. - Return to the terminal window and Ctrl D to exit the container and type
docker rm web1or keep it around if you like.
Now you will create your own Dockerfile. In the root of the training_docker repository create a directory called build3 and inside of that folder create a Dockerfile. You can get as elaborate or simple as you like with this file. At the conclusion of your Dockerfile creation git add and commit the build3 folder and Dockerfile to your forked repository for review later by the instructor.
Now that we have created images and containeres let's take a moment to practice using persistent volumes in our containers. In this first exercise you are setting up a container that creates a database that is shared with the host and the container.
- Start a container from an image we have already created but this time mount a volume in the container by typing
docker run -ti -v /Users/<yourusername>/Desktop:/shared-folder debian:stretch bash- note that the /Users//Desktop is the desktop of your Mac and the /shared-folder is the name of the folder in the container that can access your Desktop.
- Touch a file on your desktop from within the container by typing
touch sqlite.db. - Now exit the container by pressing Ctrl D and take a moment to look on your desktop to see if the file showed up. Note that the file survived the container exit and persisted on your desktop. Copy the file to your training_docker repository and git add and git commit the file to your forked repository.
In this exercise you are setting up a volume that will share data amoung two containers using an ephermeral volume.
- Start a container from an image we have already created and setup a shared volume in the container by typing
docker run -ti --name db01 -v /shared-data debian:stretch bash - Now in the commandline of the new container add data to the shared-data folder by typing
cd shared-dataand then typetouch tmp. - We need to keep the db01 container running so let's leave it running and open a new terminal tab by pressing Command T on your keyboard.
- In this new terminal window create another container that will access the db file on the container we just setup, type
docker run -ti --name web01 --volumes-from db01 debian:stretch bash. - Now you are in the web01 container bash shell type
lsand you will see the shared-data folder available on the web01 container. - Type
cd shared-dataandlsand you will see the tmp file that you created in the db01 container. - Let's add another file to this folder by typing
touch cache. - Return to the previous tab that had the db01 container running and type
exit. - Now return to the terminal tab that was running the web01 container and type
lsand you will see that even though the db01 container is gone the web01 container still has the two files (tmp & cache) that were created. - Let's start a third container for this exercise and mount the same shared-data volume by typing
docker run -ti --name db02 --volumes-from web01 debian:stretch bash. - Type
lsand you will see the shared-data folder in the new db02 container. CD into the folder and you will see the tmp and cache files as well. - Now exit both the web01 and db02 containers
- "Poof" now the data is gone and this demonstrates the very temporary nature of ephemeral volumes. Ephemeral volumes can be good for temp files or caches that can easily go away with out worry of retreival again.
Although Dockerfile supports the VOLUME directive you do not typically make an image with a specific volume in the Dockerfile. The VOLUME can be host specific and since containers are susposed to be deployable without any dependencies like local host volumes you instead create the container and specifiy the local volumes for your environment in the docker run -v hostdata:containerdata step. So therefore, this step in your training is simply to reinforce the concept that volumes are host and location specific and containers can be built to manipulate, process and transform local volumes where ever they go.
In this exercise we will setup two containers that will talk over a bridged network that we create for them to use.
- Let's first setup the network we are going to use by typing
docker network create partytime - Now let's create a web server and attach it to the partytime network. CD or change directory into the build5 directory and then CD again into the webcontainer1 folder. Now type
docker build -t nginx:web1 . - Now run the new image in a container and connect it to the network partytime by typing
docker run -ti --net=partytime --name webserver01 nginx:web1 bash - In the webserver01 container type
service nginx start - Now press Command T on your keyboard to open another terminal tab, type
cd ..to jump up one level in your repository and then typecd curlcontainer2. - Build the curl container by typing
docker build -t curl:image . - Run the curl container by typing
docker run -ti --net=partytime --name curlcontainer curl:image bash - Run the ping command by typing
ping webserver01and notice that Docker has already added the webserver01 to the hosts file so that this ping will resolve the webserver01 container. Press Ctrl C to quit the ping command. - Now type the command
curl -s http://webserver01/wineglas.vt | pv -L3000 -q - Cheers!