# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# # Your first image!
#
# Ok now that you understand what Docker is and why use it (at least I hope, if not you will soon!), it is time to get more technical.
#
# ## Goal
# In this module we will learn:
# * What is the **concrete** difference between an **image** and a **container**
# * How to create an image?
# * What is a Dockerfile and how to use it?
# * How to create a container out of an image?
#
# And we will run our very first container based on our very first image!
#
# ![do-it](./assets/do-it.gif)

# ## Installation
# First things first, we need to install Docker.
#
# You just have to follow [Docker's well made documentation](https://docs.docker.com/engine/install/ubuntu/).
#
# If you're running Windows or Mac -> https://docs.docker.com/engine/install/
#
# By default, Docker will need to use `sudo` each time. Let's change that:
# ```bash
# sudo gpasswd -a $USER docker
# ```
#
# You will need to log-out before it applies the changes.
#
# ## How do we create an image
# In order to create images (or import them), we could:
#
# ### Go to [Docker Hub](https://hub.docker.com/) 
#
# which is like GitHub for Docker images. 
# You need an image with a SQL DB in it? [There is one](https://hub.docker.com/r/mysalt/mysql). 
# You need an image with python 3.6? [There is one](https://hub.docker.com/r/silverlogic/python3.6).
# And a lot of other images!
#
# ### Create your own docker file!
#
# In many cases, we will want to create our own images, with our own files and our own script.
# In order to do that we will create what we call a `Dockerfile`. 
#
# This is just a file that is named `Dockerfile` and that contains a script that Docker can understand.
# Based on that, it will create an image.
#
# ## Let's create our image
# It's time! So we will create a `Dockerfile` and we will use a python image as base. It means that we start from an existing image to build our own.
# So we don't have to start from scratch each time.
#
# In this file we will add a line to tell Docker that we want to start from the official Python 3.7 image.
#
# The `FROM` keyword is used to tell Docker which base image we will use.
#
# ```Dockerfile
# FROM python:3.7
# ```
#
# Now let's add another line to copy a file. In the folder you're in, there is a file named `hello_world.py`. This file contains a single line:
#
# ```python
# print("Hello world!")
# ```
#
# We will create folder called `app` and put our file in it. As the python image is built on top of Ubuntu, we can use all the commands that work in Ubuntu.
#
# Let's see some useful keywords that can be used in a Dockerfile:
# * The `RUN` keyword can be uses to run a command on the system.
# * The `COPY` keyword can be used to copy a file.
# * The `WORKDIR` keyword can be used to define the path where all the commands will be run starting after it.
# * The `CMD` keyword can be used to define the command that the container will run when it will be launched.
#
#
# ```Dockerfile
# RUN mkdir /app
# RUN mkdir /app/code
# COPY code/hello_world.py /app/code/hello_world.py
# WORKDIR /app
# CMD ["python", "code/hello_world.py"]
# ```
#
# ## Let's build our image!
# Now we're ready to create our first image! Exciting right? 
#
# We say that we `build` our image. That's the term. 
#
# The command is: `docker build . -t hello`
#
# * `docker` to specify that we use docker
# * `build` to specify that we want to create an image
# * `.` to specify that the Dockerfile is in the current directory
# * `-t hello` to add a name to our image. If we don't do that we will need to use the ID that docker defines for us and it's not easy to remember.
#
# I already created the Dockerfile for you. Have a look on it!

# !docker build . -t hello

# As you can see, our image has been successfully built!
#
# If you look at the last line of the output, you see:
#
# ```
# Successfully tagged hello:latest
# ```
#
# Our image has been tagged with `hello:latest`. As we didn't define any tag at the end of our image name, `latest` will be added by docker.
# If we make changes in our image and re-build it, a new image will be created with the tag `latest` and our old image will no longer have it. 
# It's useful when you want to use the most recent version of your image.
#
# We can also add our own tags as follows

# !docker build . -t another_image:v1.0

# If we try to list all of our images, we will see that we have 3 images. 
#
# * One `hello` with the tag `latest`
# * One `hello` with the tag `v1.0`
# * One `python` with the tag `3.7` *(that's the one we used as base image)*
#
# We can see it with:
#
# ```bash
# docker image ls
# ```

# !docker image ls

# ## Manage images
# As you can see images take a lot of place on you hard drive! And the more complex your images are and the more dependencies they have, the bigger they will be.
#
# It rapidly become a pain...
#
# Thankfully, we can remove the one that we don't use anymore with the command:
#
# ```bash
# docker image rm <IMAGE_ID>
# ````
# As we see in the `docker image ls` output, each image has an ID. We will use that to remove them. Let's say we want to remove our `hello:v1.0` image.
# ```
# hello               latest              8f7ca704c0a8        7 minutes ago       876MB
# ```
# Here the ID is `8f7ca704c0a8`. But here multiple images have the same ID. That's because multiples images you the same image.
#
# Confused? It's because Docker is really smart! We tried to create multiple images based on the same Dockerfile, and there were no changes between the creation of the first image and the last one. Neither in the files, nor in the Dockerfile. So Docker knows that it doesn't have to create multiple images! It creates and 'links' it to other tags.
#
# So if I try to delete with the ID it will give me a warning and not do it. Because multiple tags are linked to the same image.
#
# So instead of using IDs we will use tags.

# !docker image rm hello:v1.0

# The tag has been removed!

# !docker image ls

# ## Run it
# Perfect! You understand what an image is now! Let's run it. 
#
# When we will run the image, Docker will create a `container`, an instance of the image and it will execute the command we added after the `CMD` keyword.
#
# We will do it with the command:
# ```bash
# docker run -t hello:latest
# ```
#
# * `run` is to tell to docker to create a container.
# * `-t hello:latest` is to specify which image it should use to create and run the `container`
#
# If you don't put `:<YOUR_TAG>` docker will add `:latest` by default.

# !docker run -t hello

# Our container successfully ran. We can see that it printed 'Hello world' as asked.
#
# Ok. So we created a container and we ran it. Can we see it stored somewhere?
#
# Let's try with `docker container ls` maybe?

# !docker container ls

# Damn it, the command seems to be right but there is nothing here!
# Well, `docker container ls` only show running containers. And this one is not running anymore because it completed the task we asked him to do!
#
# So if we want to see all the container, including the stopped one, we can do:
# ```bash
# docker container ls -a
# ```
#

# !docker container ls -a

# Ok good! We can of course remove it with:
#
# ```bash
# docker contaier rm <CONTAINER_ID>
# ```
#
# So in this case `cd585b842f8b`

# !docker container rm cd585b842f8b

# It worked!
#
# ## Conclusion
# Great! You now have a complete understanding of images and containers. 
#
# In the next module, we will dive deeper into the container and see what we can do with them.
#
# ![We will have so much fun!](./assets/have-fun.gif)

StarcoderdataJupyterScriptsDedupFiltered