Dockerイメージ データの永続化 コンテナと接続する
Docker Compose

インストール

VScodeにRemote Developmentをインストール(DevContainers内包)

Snippet

Docker

docker pull ubuntu:22.04

docker image ls -a

docker container ls -a
docker container run -it
docker container exec [container-name] bash

Docker Compose

# 複数コンテナを一気に作成する
docker compose up (-d)

# 起動中のコンテナを確認
docker compose ps

# bashでコンテナに入る
docker compose exec [container-name] bash

# コンテナを全て終了する
docker compose down

# make sure the version of web container
node --version
v18.20.3

Dockerイメージ

コンテナの型となるテンプレ
 スクリプト・バイナリ・ファイルシステム・環境変数など

docker image pull {イメージ名}

docker image build {コンテキストパス}

docker image inspect {イメージ名}  # イメージの詳細情報
docker image ls
docker image rm {イメージ名}
docker container run {イメージ名} {立ち上げ直後に実行したいコマンド名}
docker container run -itd --rm --name {コンテナ名} --network {NW名} {イメージ名}

-i --interactive  標準入力CLOSED → OPENにするOP
-t --tty  出力を整形する疑似テレタイプライター
-d --detach  バックグラウンド実行(デタッチトモード)
--net --network  ネットワークに接続する

docker container ls
docker container inspect {コンテナ名}  # コンテナの詳細情報

docker container restart {コンテナ名} # 再度UP状態にする
docker container stop {コンテナ名} # 止めてExited状態にする

docker container rm {コンテナ名}  # Exitedコンテナを削除する
docker container rm -f {コンテナ名}  # 動作中のコンテナでも強制削除できる
docker container prune  # Exitedコンテナを全て廃棄

Upコンテナに対してコマンド実行を指示
 コンテナ内にログインしなくてもコマンドを実行できる

docker container exec -it {コンテナ名} {実行させるコマンド}

-i --interactive  標準入力CLOSED → OPENにするOP
-t --tty  出力を整形する疑似テレタイプライター
-d --detach  バックグラウンド実行(デタッチトモード)

例)docker container exec -it my-ubuntu-1 ping -c 4 8.8.8.8
docker container detatch {コンテナ}  # デタッチしてバックグラウンドで実行する
docker container attach {コンテナ}  # アタッチしてフォアグラウンド操作できるようにする

データの永続化

ボリューム

container-1 container-2
    volume を共有

docker container run -v {Vol名}:{コンテナ内絶対パス} --name {コンテナ名} {イメージ}
例)docker container run -it -v my-volume:/app1 --name container-1 ubuntu:22.04

バインドマウント

PCのローカル任意ディレクトリ と Dockerコンテナの任意ディレクトリ を同期させる

docker container run -v {ホスト絶対パス}:{コンテナ内絶対パス} {イメージ}
例)docker container run -it -v my-volume:/app1 --name container-1 ubuntu:22.04

docker container run -it -v C:\USERS\ISDMS\ONEDRIVE\ドキュメント\DOCKER\UDEMY\MY-DIR:/app ubuntu:22.04
docker container run -it -v $(pwd)\MY-DIR:/app ubuntu:22.04

ボリュームとバインドマウントの使い分け

ボリューム(Docker内部)バインドマウント(ホストと同期)
複数のコンテナ間でのデータ共有可能か?YESYES
ホストからのデータアクセス可能か?NOYES
ホストの環境に依存するか?NOYES

ボリューム【推奨】= ホスト環境で左右される(データベースはボリュームに置くのが基本)
バインドマウント = 開発中など、ホストから積極的にコンテナデータへアクセス/共有が必要な時


コンテナと接続する

コンテナのポート制御(ホストマシン⇔コンテナ)

ポート番号が開いていないと(PORTをホストと接続していないとアプリに)アクセスできない
例)80番でNginxにアクセス

ホストとコンテナのポートを紐づける

docker container run -p {ホスト側のポート}:{コンテナ側のポート} {イメージ}

コンテナのネットワーク制御(コンテナ⇔コンテナ)

複数のコンテナを同時に立ち上げることが普通になっている。

コンテナ同士の通信を簡単にしたり、不要なコンテナ同士の通信を防ぐために隔離する

docker network ls
NETWORK ID     NAME    DRIVER    SCOPE
xxxxxxxxxx    bridge   bridge    local ← 最重要
xxxxxxxxxx    host     host      local
xxxxxxxxxx    none     null      local

ブリッジネットワーク

複数のコンテナ同士の通信を橋渡しする

docker container run -itd --rm --name my-nginx-1 nginx
docker network inspect {ネットワーク名}  # bridge/host/none

docker network create my-net
docker network ls

docker container run -itd --rm --name my-nginx-2 --network {ネットワーク名} {イメージ}
docker network inspect my-net

ブリッジネットワーク内で通信をする

Dockerfile
FROM ubuntu:22.04
RUN apt update && apt install -y iputils-ping curl
CMD ["bash"]
# ------------
docker image build -t my-ubuntu .

docker container run -itd --name my-ubuntu-1 my-ubuntu  # デフォルトでbridgeに所属
docker container run -itd --name my-ubuntu-2 --network my-net my-ubuntu


ブリッジネットワークでの名前解決
 ※デフォルトのbridgeネットワーク内では使えない

docker container exec -it my-ubuntu-1 bash
root@xxx:/# curl http://my-nginx-1

> curl: (6) Could not resolve host: my-nginx-1  # デフォルトbridge NW内だとダメ


docker container exec -it my-ubuntu-2 bash

> root@xxx:/# curl http://my-nginx-2
<html>
<head>
<title>Welcome to nginx!</title>
<style>
 ・・・・
<p><em>Thank you for using nginx.</em></p>
</body>
</html>

ブリッジネットワークの削除

docker network rm {ネットワーク名}


Docker Composeで複数コンテナを扱う

Docker Composeとは?
・多くのDockerコマンドを実行するのは大変
・他人に同じ環境を共有するのが困難
        ↓
    Docker Composeが解決する


/webapi
 ├ /api
 |├ Dockerfile
 |├ /src/main/java/com/example/api
 | ├ ApiApplication.java
 | ├ HelloController.java
 ├ docker-compose.yml


docker-compose.yml ヤムルにport、network, volume設定を書く

docker compose up  # このymlファイルに書かれた通りの条件でコンテナが立ち上がる

コンテナ条件

           Custom Bridge
         ↑↓        ↑↓
8080 → 8080 container → 5432 container ⇔ Volume
       spring boot     PostgreSQL
        api         db    db-storage


spring initializr(Java)から、APIサーバのイメージを作る

Project:Gradle-Groovy  Langage:Java  Spring Boot:3.2.5
Project Metadata:Artifact/Name = api  Packaging:Jar  Java:17
Dependencies:Spring Web, Spring Data JPA, PostgreSQL Driver, H2 Database


APIサーバの動作を定義するJavaファイルを作成

\webapi\api\src\main\java\com\example\api\HelloController.java

package com.example.api;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api")
public class HelloController {
    @RequestMapping("/hello")
    public String hello(
            @RequestParam String lang
    ) {
        return "HELLO";
    }
}

\webapi\api\Dockerfile

FROM gradle:7

WORKDIR /api
COPY . .

CMD [ "./gradlew", "bootRun" ]


まず試しにapiサーバー設定を試してみる

イメージをビルド

docker image build -t api-img .  # -t タグ

docker image ls
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
api-img      latest    3cb713f05d03   25 minutes ago   702MB

コンテナを起動

docker container run -p 8080:8080 --rm api-img  # 実験なので--rmつけとく

Downloading https://services.gradle.org/distributions/gradle-8.7-bin.zip
............10%.............20%.............30%.............40%............50%.............60%.............70%.............80%.............90%............100%

Welcome to Gradle 8.7!

Here are the highlights of this release:
 - Compiling and testing with Java 22
 - Cacheable Groovy script compilation
 - New methods in lazy collection properties

For more details see https://docs.gradle.org/8.7/release-notes.html

Starting a Gradle Daemon (subsequent builds will be faster)
> Task :compileJava
> Task :processResources
> Task :classes
> Task :resolveMainClassName

> Task :bootRun

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v3.2.5)

# 起動した

ブラウザのURLに
 http://localhost:8080/api/hello?lang=ja

この内容でAPIサーバを作成しよう


Docker Composeを使って一気にAPIサーバを起動するコンテナを立ち上げる

/webapi
 ├ /api
 |├ Dockerfile
 |├ /src/main/java/com/example/api
 | ├ ApiApplication.java
 | ├ HelloController.java
 ├ docker-compose.yml


# webapi 配下にdocker-compose.yml ファイルを作成

version: '3.9'
services:
  api:
    build: ./api
    ports:
      - 8080:8080

これを

docker compose up

することで、
 docker image build -t api-img ./api
 docker container run –name api -p 8080:8080 api-img
をいっぺんに実行したのと同じ効果が得られる。
       ↓

localhost:8080/api/hello?lang=今はなんでもいい

同じようにWebAPIが立ち上がった



Docker Composeを使って一気にDBを起動するコンテナを立ち上げる

/webapi
 ├ /api
 |├ Dockerfile
 |├ /src/main/java/com/example/api
 | ├ ApiApplication.java
 | ├ HelloController.java
 ├ /db/initdb
 | ├ 1-create-greetings.sql
 | ├ 2-insert-greetings.sql
 ├ docker-compose.yml


docker-compose.ymldb: 以下を追記

version: '3.9'
services:
  api:
    build: ./api
    ports:
      - 8080:8080
  db:
    image: postgres:15
    ports:
      - 5432:5432
    environment:
      - POSTGRES_PASSWORD=mypassword
      - POSTGRES_USER=postgres
      - POSTGRES_DB=appdb
    volumes:
      - db-storage:/var/run/postgresql/data  # /var/lib/ではなかった
      - ./db/initdb:/docker-entrypoint-initdb.d

volumes:
  db-storage:

1-create-greetings.sql

CREATE TABLE greetings (
    id SERIAL,
    lang VARCHAR(255) NOT NULL,
    text VARCHAR(255) NOT NULL,
    PRIMARY KEY (id)
);

2-insert-greetings.sql

INSERT INTO greetings (lang, text)
VALUES
    ('ja', 'こんにちは'),
    ('en', 'Hello')
;

docker compose からDBコンテナだけを立ち上げる

docker compose up db -d

DBの中を確認

docker compose exec db bash

root@7494e39143b3:/# psql -U postgres

psql (15.6 (Debian 15.6-1.pgdg120+2))
Type "help" for help.

postgres=# \l
                                                List of databases
   Name    |  Owner   | Encoding |  Collate   |   Ctype    | ICU Locale | Locale Provider |   Access privileges
-----------+----------+----------+------------+------------+------------+-----------------+-----------------------        
 appdb     | postgres | UTF8     | en_US.utf8 | en_US.utf8 |            | libc            |
 postgres  | postgres | UTF8     | en_US.utf8 | en_US.utf8 |            | libc            |
 template0 | postgres | UTF8     | en_US.utf8 | en_US.utf8 |            | libc            | =c/postgres          +        
           |          |          |            |            |            |                 | postgres=CTc/postgres
 template1 | postgres | UTF8     | en_US.utf8 | en_US.utf8 |            | libc            | =c/postgres          +        
           |          |          |            |            |            |                 | postgres=CTc/postgres
(4 rows)

postgres=# \c appdb
You are now connected to database "appdb" as user "postgres".
appdb=# \dt

一旦、docker composeで作ったコンテナを全て落とす

docker compose down
[+] Running 3/3
 ✔ Container webapi-db-1   Removed
 ✔ Container webapi-api-1  Removed
 ✔ Network webapi_default  Removed


④APIコンテナとDBコンテナを接続する

/webapi
 ├ /api
 |├ Dockerfile
 |├ /src
 | ├ /main
 | | ├ /java/com/example/api
 | |   ├ /entities
 | |   | ├ GreetingEntity.java
 | |   ├ ApiApplication.java
 | |   ├ GreetingRepository.java
 | |   ├ HelloController.java
 | ├ /resources
 |   ├ application.properties
 ├ /db/initdb
 | ├ 1-create-greetings.sql
 | ├ 2-insert-greetings.sql
 ├ docker-compose.yml


GreetingRepository.java

DBコンテナへ接続するためのレイヤーを作成

package com.example.api;

import com.example.api.entities.GreetingEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import jakarta.transaction.Transactional;

@Repository
@Transactional
public interface GreetingRepository extends JpaRepository<GreetingEntity, String> {
    GreetingEntity findFirstByLang(String lang);  /*ここで接続*/
}

/entities/GreetingEntity.java

package com.example.api.entities;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;

@Entity
@Table(name = "greetings")
public class GreetingEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    public Long id;  /* DBテーブルのスキーマ */
    public String lang;  /* (1-create-greetings.sql) */
    public String text;  /* と一致させている */
}

HelloController.java 修正

package com.example.api;

import com.example.api.entities.GreetingEntity;  /*追加*/
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api")
public class HelloController {
    @Autowired
    private GreetingRepository repository;  /*インスタンス作成*/
    
    @RequestMapping("/hello")
    public String hello(
            @RequestParam String lang
    ) {
        GreetingEntity entity = this.repository.findFirstByLang(lang);  /*DBからlangの値を取得*/
        return entity.text;  /*値を返す*/
    }
}

application.properties 追記
 ※spring boot全体の環境変数を定義するファイル

spring.application.name=api
spring.datasource.url=jdbc:postgresql://db:5432/appdb
spring.datasource.username=postgres
spring.datasource.password=mypassword
spring.datasource.driver-class-name=org.postgresql.driver
spring.jpa.hibernate.ddl-auto=none

docker-compose.yml 追記

version: '3.9'
services:
  api:
    build: ./api
    ports:
      - 8080:8080
    depends_on:  # ここを追記
      - db
  db:
    image: postgres:15
    ports:
      - 5432:5432
    environment:
      - POSTGRES_PASSWORD=mypassword
      - POSTGRES_USER=postgres
      - POSTGRES_DB=appdb
    volumes:
      - db-storage:/var/run/postgresql/data # /var/lib/じゃないじゃん!
      - ./db/initdb:/docker-entrypoint-initdb.d

volumes:
  db-storage:


⑤いよいよ docker compose をリビルド

–build オプションを付けることでイメージの作り直しが行われる
※–buildをつけないと、以前のイメージを使ってしまう為

docker compose up --build


udemy セクション11 実務想定Webアプリ開発体験

docker compose up -d
docker compose ps

container_name: api - React(gradle)
port: 8080
docker compose exec api bash
cd /workspace
./gradlew bootRun

container_name: web - springboot(Node.js)
port: 3000
docker compose exec web bash
cd /workspace
npm install
npm run start

AWSで、GitHubActionsからAWS ECR(DockerHubのAWS版みたいなの), ECSにアクセスできるTokenを発行する

許可するポリシー
 AmazonEC2ContainerRegistryPowerUser
 AmazonECS_FullAccess

アクセスキーを作成

ECRでプライベートリポジトリの作成

ECSでクラスターの作成

タスク定義
 Amazon ECR Public Gallery からnginxのイメージを採用

クラスターの中にサービスを作成