Dockerを触り始めて１日目の人が教えるDockerfile入門

Dockerってなんとなく分かった！コマンドもHelloWorldできたので実践してみよう！という人が書いた記事です。
同じような状況の方の参考になれば幸いです！

:::note alert
昨日Dockerを触り始めた人が学習した内容をアウトプットするために随筆した記事です。間違っていることが多数存在する可能性があります。
:::
:::note warn
Linux系のコマンドがわからない人は少しつらいかもしれません。（Dockerfile内には基本的にコマンドを書き込んでいきます。）
:::

# Dockerのコマンドで分かりやすい解説

https://qiita.com/wMETAw/items/34ba5c980e2a38e548db



# Dockerfileとは？
中身はテキストファイルです。
元となるイメージに対して、必要な設定（例えば`apt-get`）などを加えたイメージが作成できます。
例えば、Apacheイメージだけでは何もページがありませんが、ポートの変更、ファイル(htmlやcssなど)を追加したイメージを作ることができます！
つまり、プログラミングをして元のデータに〇〇をして△△をするといった感じです。（ここにコマンドの知識が必要となってきます。）
![プレゼンテーション1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/362835/4adceadb-ff71-1f38-6bfd-70f0734dec4e.png)


## 実践
試しにApacheにHelloWorldと表示されるHTMLファイルが搭載されているイメージを作ってみる

```Dockerfile:Dockerfile
#1
FROM httpd:2.4.52
#2
COPY ./index.html /usr/local/apache2/htdocs
#3
WORKDIR /usr/local/apache2/htdocs/
#4
RUN ["apt","update"]
RUN ["apt","install","-y","curl"]
RUN ["touch","test.html"]

RUN echo 'Hello World 2' >> ./test.html && \
echo 'good!' >> ./test.html
#5
ENTRYPOINT httpd\
&& curl localhost\
&& curl localhost/test.html
```
```html:index.html
<!DOCTYPE HTML>
<html lang="ja">
    <head><meta charset="utf-8"><title>Test</title></head>
    <body>Hello World!</body>
</html>
```

#解説
## ＃1 FROM
今回は複雑なことを扱わないので公式バージョンを利用します。ここの説明だけ少し長いです。

Dockerfile内のFROMはベースとなるイメージを指定したものになります。<a href="https://docs.docker.jp/engine/reference/builder.html#from">（リファレンス）</a>
GUIベースだと<a href="https://hub.docker.com/">DockerHub</a>で検索します。
例えば今回の場合はApache(httpd)なのでApacheと検索してみます。

そうすると、イメージ一覧が出てくるので、使いたいものをクリックしてみましょう。
Dockerの醍醐味である環境が同じものを複数用意できるという特性上、バージョンを指定してあげたほうが良いらしいです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/362835/cd1a2ea6-05b4-496e-3705-6bb49b8e8ba1.png)
そのため、Descriptionに`Supported tags and respective Dockerfile links`とありますから、そこから利用したいイメージを探せば良いです。`alpine`とか`slim`など色々あり、どれを選べばいいの？となりますが、**バージョン・OS・Slim**の３つを利用者側が選択すれば良いわけです。

###OSについて
|名称|説明|
|-|-|
|公式(alpineなど何もついていない)|作成者が用意している基本的なイメージ|
|alpine|軽量重視Linuxディストリビューション。軽量化しているので必要なライブラリがない可能性がある。初心者向けではないらしい。しかしその分ファイルサイズは小さくなる。|
|bullseye,buster,stretch,jessie|Debian。安定して使うことができる。左からバージョン11,10,9,8|
|windowsservercore|Windows環境。|
###Slimについて
必要でない部分をそぎ落としたバージョンのことです。調べている感じ、

 - 軽量化
  - alpine>slim>Debian
 - ファイルサイズ
  - alpine<slim<Debian
 
 という感じがする。（詳しくないのであいまいな感じです）

https://prograshi.com/platform/docker/docker-image-tags-difference/

## ＃2 COPY
ファイルをコピーします。

```
COPY [Dockerfileからの相対パス] [コンテナ内のパス]
```
という形で指定します。

##WORKDIR・RUN
さて、COPYにて指定したフォルダにファイルを置くことはできましたが、今度は任意の場所にコンテナ内からファイルを作成してみましょう！
### ＃3 WORKDIR
`WORKDIR パス`にて、コンテナ内のどのフォルダで作業するか決めます。Linuxの`cd`コマンドと似た感覚です

### ＃4 RUN
`RUN ["コマンド",~]`にて実行するコマンドを指定します。これはイメージの作成時に実行されます。配列になっていますが、すべての要素が半角スペース区切りで実行されます。配列を使わないことも可能です。複数行にわたって記入するときは`\`を利用しましょう。

## ＃5 ENTRYPOINT・CMD
本サンプルではENTRYPOINTを利用しましたが、仲間としてCMD、そして実行時の引数(`docker run packagename 実行するコマンド`が存在します。
こちらで記入したものはコンテナ生成時に実行されるものです。このサンプルではhttpdを起動し、curlにてlocalhostを確認しています。
ENTRYPOINTがあれば強制的に実行(CMDと引数は実行されない)、
ENTRYPOINTがない場合には、CMDは引数が設定されていない時に実行、引数が設定されていればそちらを実行します。


https://www.guri2o1667.work/entry/2021/06/08/%E3%80%90Docker%E3%80%91Dockerfile%E3%81%A7%E8%A8%98%E8%BF%B0%E3%81%99%E3%82%8BRUN%E3%81%A8CMD%E3%81%A8ENTRYPOINT%E3%81%AE%E9%81%95%E3%81%84%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6

# ビルドする
Dockerfileなどが置いてあるディレクトリにて次のコマンドを実行します。

```shell-session
docker build -t イメージ名:タグ名 Dockerfileのディレクトリ
 # 実行例
docker build -t miyayu/apachetest:1.0 .
```
Docker imagesをして作ったイメージがあればOKです。
# 実行する
```shell-session
docker run -rm イメージ名:タグ名
 # 実行例
docker run -rm miyayu/apachetest:1.0
 # 出力
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message
(略)
<!DOCTYPE HTML>
<html lang="ja">
    <head><meta charset="utf-8"><title>Test</title></head>
    <body>Hello World!</body>
</html>  % Total   (略)     0Hello World 2
good!(略)
```
#チャレンジ問題
AH00558エラーに関してはこちらの記事が参考になるかと思います。チャレンジ問題としてエラーを解決してみてください！！

https://ex1.m-yabe.com/archives/2965

##ヒント
###コマンドを実行する方法
設定ファイルがどこにあるか探すためにlsなどを使いたいですか？そんなときにはEntrypointに`/bin/bash`というコマンドを追加してみましょう！（設定ファイルは`/usr/local/apache2/conf/httpd.conf`です。）
`docker run`時に`-it`をつけることでコンテナを操作することが可能になります。（`exit`コマンドで終了できます。）
ちなみに`--rm`オプションはexit時にデータを削除するものなので、保存したデータをもう一度見たいなど思ったら必要に応じて外してみてください。
あ、根本的な解決はDockerfile内で行ってくださいね？
<details><summary>コマンドを実行する方法の答え（クリックで開く）</summary><div>

```Dockerfile:Dockerfile
ENTRYPOINT httpd\
&& curl localhost\
&& curl localhost/test.html\
&& /bin/bash
```

</div></details>
###文字列を置き換える方法

sedコマンドをRUN内で実行してみましょう！（ディレクトリ移動も忘れずに）

<details><summary>実行するコマンドを確認する（クリックで開く）</summary><div>

```shell-session
sed -i -e 's/#ServerName www.example.com:80/ServerName www.example.com:80/g' httpd.conf
```

</div></details>
<details><summary>文字列を置き換える方法の答え（クリックで開く）</summary><div>

```Dockerfile:Dockerfile
WORKDIR /usr/local/apache2/conf/
RUN ["sed","-i","-e","s/#ServerName www.example.com:80/ServerName www.example.com:80/g","httpd.conf"]
```

</div></details>