# Docker file

## What is Dockerfile? <a href="#dockerfile-la-gi-0" id="dockerfile-la-gi-0"></a>

Dockerfile is a file consisting of a collection of directives, which when Docker calls the file, it can automatically create images. See more <https://docs.docker.com/engine/reference/builder/>

## Some commands used in Dockerfile: <a href="#mot-so-lenh-dung-trong-dockerfile-1" id="mot-so-lenh-dung-trong-dockerfile-1"></a>

**FROM** Is the base image for us to build a new image. This directive must be placed at the top of the Dockerfile

```docker
FROM <image> [AS <name>]
FROM <image>[:<tag>] [AS <name>]
FROM <image>[@<digest>] [AS <name>]
MAINTAINER Chứa thông tin của tác giả tiến hành build image.
```

**RUN** Used when you want to install additional packages during the image build process.

```docker
RUN <command>
RUN [“executable”, “param1”, “param2”]
```

**COPY** This directive is used to copy a new file or directory from the source (src) and move it to the destination (dest) in the container's file system. Source here can be the local host path or URL. COPY has 2 forms:

```docker
COPY [–chown=<user>:<group>] <src>… <dest>
COPY [–chown=<user>:<group>] [“<src>”,… “<dest>”] (requires path to contain spaces)
```

**ENV** Defines environment variables

```docker
ENV <key> <value>
ENV <key>=<value> …
```

**EXPOSE** Used to declare the listening ports of the container.

```docker
EXPOSE <port> [<port>/<protocol>…]
```

Combine with the -p parameter to expose the container's port to the outside (NAT port)

**CMD** Is a directive indicating which command is executed each time the container is initialized. In the Dockerfile there is only one CMD directive

```docker
CMD [“executable”,”param1″,”param2″] (exec form, this is the preferred form)
CMD [“param1″,”param2”] (as default parameters to ENTRYPOINT)
CMD command param1 param2 (shell form)
```

**ENTRYPOINT** allows configuring a container that runs as an executable. ENTRYPOINT will overwrite the elements used by the CMD directive.

```docker
ENTRYPOINT [“executable”, “param1”, “param2”] (exec form, preferred)
ENTRYPOINT command param1 param2 (shell form)
```

#### **For example: docker run -it centos top -H**

**CMD** and **ENTRYPOINT** interaction . Both commands determine which command is executed when running a container.

There are several rules in the interaction between the two commands:

At least 1 directive will be specified in the Dockerfile (of course it is possible for 2 directives to appear in the Dockerfile)

* **ENTRYPOINT** is defined when using the container as an executable command
* **CMD** is used as a way to specify default parameters for an ENTRYPOINT directive or execute a command within a container
* **CMD** will be overwritten when running containers with interleaved parameters.

**Example of CMD & ENTRYPOINT in Dockerfile:**

```docker
ENTRYPOINT [“/usr/sbin/apache2ctl”]
CMD [“-D”, “FOREGROUND”]
ADD
```

**The ADD** directive is used to copy files, directories, or files with URLs from the source (src) and add them to the destination path (dest) in the image's file system.

**ADD** has 2 forms:

```docker
ADD [–chown=<user>:<group>] <src>… <dest>
ADD [–chown=<user>:<group>] [“<src>”,… “<dest>”] (this form is required for paths containing whitespace)
```

**Note** : Note the difference between **COPY/ADD** . **COPY** supports copying only local paths; ADD can support **copying** .tar compressed files and support URL paths.

**WORKDIR** Is a directive used to set up the working directory. It is the same as the home directory, in this case the home directory of the container. When calling **WORKDIR,** it will create a directory the first time it is called and access it as the home directory. It can be used multiple times in a Dockerfile.

```docker
WORKDIR /path/to/workdir
```

**USER**

Used to set the user to use when running the image and for some directives: **RUN, CMD & ENTRYPOINT** in the Dockerfile.

**VOLUME**

Used to mount files/directories between host and container. The purpose of VOLUME is:

* Retains data when container is removed
* Share data between host and container
* Share data between containers

**Perform image build with Dockerfile**

Let's test build the nginx installation package on centos:7 base image (CentOS7:nginx). Create a Dockerfile file with the following content:

```docker
FROM centos:7
MAINTAINER TonyLe
RUN yum -y install epel-release && yum -y install nginx
#Running with FOREGROUND
CMD ["nginx", "-g", "daemon off;"]
```

**Run Nginx in FOREGROUND** mode (by default, nginx runs in BACKGROUND mode – daemon on)

Build image

```docker
docker build -t TonyLe/CentOS7-Nginx.
```

Run container

```docker
docker run -it -p 8080:80 TonyLe/CentOS7-Nginx
```

## Best tips with Dockerfile <a href="#id-33-best-tips-voi-dockerfile-10" id="id-33-best-tips-voi-dockerfile-10"></a>

1. Search for the application you want to run instead of using the os from FORM and then install that application on the os.
2. To version the application to distinguish the versions is really necessary.
3. Using Alpine, reduces storage space compared to using os.
4. A RUN command runs corresponding to a generated layer. So if possible, combine commands into one RUN command using &&
5. Instructions with few changes should be placed above, many changes below so that when Docker performs the build faster because it can reload the previously built cache.
6. Use .dockerignore
7. A Dockerfile can be used to run multi builds.
8. Use run user policies to ensure security.
9. Docker scan or CICD should be used to scan for vulnerabilities.

## Create Dockerfile with Visual Studio 2022 <a href="#id-34-tao-dockerfile-voi-visual-studio-2022-11" id="id-34-tao-dockerfile-voi-visual-studio-2022-11"></a>

With a real project, there will be many issues that need attention such as technology changing rapidly and updating new technology versions must be done regularly.\
In the actual case, when you deploy the system to Amazon's ECS, the running netCore version is 5 and need to be updated to version 6. For you to write a Dockerfile for the source yourself is very difficult because you do not code the entire project so it is difficult to understand everything. Folders and paths need to be copied and edited in Dockerfile. You will have to sit and fix each small section, which is very time consuming. The optimal solution for those who know how to apply technology is to use Visual Studio 2022 to automatically create a Dockerfile that matches your project.

**The steps will be:**\
Open the project with Visual Studio 2022 \
Select the .sln file\
Create Dockerfile\
Select OS\
And name, you have a Dockerfile most suitable for your project.<br>

<figure><img src="https://images.viblo.asia/86c79b8f-9c77-43a8-954f-24075b01d2a0.png" alt=""><figcaption></figcaption></figure>

<figure><img src="https://images.viblo.asia/13bdaf80-c303-42f9-8cfd-062de233aea1.png" alt=""><figcaption></figcaption></figure>

<figure><img src="https://images.viblo.asia/c7dcf496-6c3b-4550-805b-f4cfd1e0a86b.png" alt=""><figcaption></figcaption></figure>

<figure><img src="https://images.viblo.asia/b5c0db8e-35f3-44fd-89f7-1e55b9276391.png" alt=""><figcaption></figcaption></figure>

<figure><img src="https://images.viblo.asia/38de4d4e-5f55-4484-8e2b-6c2988aeaee5.png" alt=""><figcaption></figcaption></figure>
