勉強したことについてまとめるサイト

勉強したことをまとめるだけのサイト、数学、プログラミング、機械学習とか

データ構造とアルゴリズム:cocktail(シェーカーソート)

cocktail(シェイクソート)

カクテルをシェークするような動きをするのでこのような名前がつけられている。bubbleソートの改良版でbubbleソートにかなり類似しておりbubbleソートを振る、ようなイメージ。

まず、左から右に配列を見ていって小さければ入れ替え、というのはbubbleソートの時と同様。 ただ、swap = Falseというフラグがあり、その周回の時に入れ替えが起きたらSwapをTrueに変更する。一番右のlimitまできたらswapをFalseに直して、今度は右から左に数字を見る。

この時に左の方が大きければ、右と入れ替える。という作業を行う。一番大きい数値は最初の段階で一番右にくるのでlimitを一つ下げる。 スクリーンショット 2020-11-25 0.54.25.png (223.0 kB)

スクリーンショット 2020-11-25 0.54.58.png (239.5 kB)

右から左に来るときは、一番左の数値が一番小さい数値になるので左側のlimitを一つ上げるようにする。

スクリーンショット 2020-11-25 0.57.47.png (244.1 kB)

一度もswapがTrueにならなかったらその時点でソートを完了して良い。そのため、swapが Trueにならない周回があったらその時点でソートが完了しているとみなしても良いため、全てのパターンを行う必要がなくBubbleソートよりも早く処理が完了する。 スクリーンショット 2020-11-25 0.58.54.png (309.7 kB)

  • まずswapの初期値がTrueなのでwhile swappedの箇所でwhilteのloopに入る。
  • 通常のbubbleソート同様に左の数値が大きければ右の数値と入れ替えるというのを1重のfor文で実現する
  • ①の最後でもしswappが起こればswappedフラグをTrueにする。
    • この時点で、swappedがFalseのままであれば、その時点でソート完了し、breakとなる
    • 初期でendを−1している理由は、最初のfor文で一番後ろに最大値が移動するので一番後ろまで処理する必要がないから
  • そのご②に入る
    • ②に入る前にend - 1をしてあげることで、limitを一つずらす
  • for i in range(end-1, start-1, -1):というfor文は配列を逆順に入れる作業をしている
    • この逆順にする作業で、for文を逆から読み込ませる作業を行なっている。実際に行っているのは通常のbubbleソートの逆順にしたバージョンである。
    • 最後にもしswapped = Trueになれば再度一番上に戻り①からやり直しswapped = Falseのまま続くまで行う。
from typing import List

def cocktail_sort(numbers: List[int]) -> List[int]:
    len_numbers = len(numbers)
    swapped = True
    start = 0
    end = len_numbers - 1
    
    while swapped:
        swapped = False
        # 右方向に進むときの for loop
        # for①=============================start
        for i in range(start, end):
            if numbers[i] > numbers[i+1]:
                numbers[i], numbers[i+1] = numbers[i+1], numbers[i]
                swapped = True
        # for①=============================end
        
        # swappが変更されなければfalseのままなのでここで処理が終了
        if not swapped:
            break

        swapped = False
        end = end - 1
        
        # for②=============================start
        for i in range(end-1, start-1, -1):
            if numbers[i] > numbers[i+1]:
                numbers[i], numbers[i+1] = numbers[i+1], numbers[i]
                swapped = True
        # for②=============================end
        start = start + 1
    
    return numbers


import random
arry = [random.randint(0, 100) for i in range(10)]
print(cocktail_sort(arry))


[0, 5, 36, 44, 53, 55, 68, 83, 84, 96]

このサイトのgif?がすごくわかりやすいのだが、右に行くときは大きいものを一番右に押しやる作業、左に行くときは小さいものを一番左に押しやる作業を行なっているのがわかる。 眺めていられるシェーカーソートのシミュレーション|JavaScript

ダウンロード.png (32.9 kB)

データ構造とアルゴリズム:本編

アルゴリズムの重要性

GAFAシリコンバレーの企業面接には絶対にアルゴリズムのコーディング試験があり、1秒でも処理が早くなるのであればアルゴリズムを早い方に書き換えたほうが良い。車の自動運転など瞬間の判断に関わるものは特に反応速度が重要視されているので、アルゴリズムについて精通していたほうが良い。

データ構造

スクリーンショット 2020-11-24 21.23.29.png (260.3 kB)

データ構造とアルゴリズムとは?

  • データをどのように格納するのか
  • どのような格納順で実装すると処理が早くなるのかなどの構造のこと

Big O Notation (Big O 記法)

learn-programing.hatenablog.jp

安定ソート

スクリーンショット 2020-11-24 22.22.03.png (606.3 kB)

安定ソートとは

ソート判定において、同一であると判断された入力データの順序がソート後も変わらない スクリーンショット 2020-11-24 22.23.46.png (1.1 MB)

元の配列のソート順は変わらない

ex) (2, Bill) , (2, June) という要素はstable sortでは元の順番が変わっていないが、unstable sortではそれぞれの順番が変わっている。

ソート

bogoソート

learn-programing.hatenablog.jp

bubbleソート

learn-programing.hatenablog.jp

cocktail(シェーカーソート)

learn-programing.hatenablog.jp

データ構造とアルゴリズム:Big O Notation (Big O 記法)

スクリーンショット 2020-11-24 21.24.17.png (253.0 kB)

アルゴリズムの処理速度を可視化したもの。

O(log(n))

# O(log(n))
def func2(n):
    if n <= 1:
        return
    else:
        print(n)
        func2(n/2)
func2(10)

10
5.0
2.5
1.25

O(n)

# O(n)

def func3(numbers):
    for num in numbers:
        print(num)
        
func3(range(1,10))

1
2
3
4
5
6
7
8
9

O(n * log(n))

# O(n * log(n))
def func4(n):
    for i in range(int(n)):
        print(i, end=' ')
    print()

    if n <= 1:
        return
    func4(n/2)

func4(10)

0 1 2 3 4 5 6 7 8 9 
0 1 2 3 4 
0 1 
0 

O(n**2)

for文を2回回すと2乗になる

# O(n**2)
# for文を2回回すと2乗になる
def func5(numbers):
    for i in range(len(numbers)):
        for j in range(len(numbers)):
            print(numbers[i], numbers[j])
        print()

func5([1,2,3,4,5])

1 1
1 2
1 3
1 4
1 5

2 1
2 2
2 3
2 4
2 5

3 1
3 2
3 3
3 4
3 5

4 1
4 2
4 3
4 4
4 5

5 1
5 2
5 3
5 4
5 5

データ構造とアルゴリズム:Bogoソート

bogo(ボゴソート

ボゴソートはシャッフルに並び替えた後にそのソートが正しく並び替えられているかを確認するソート手法。 def in_orderでは、左側の数字が右側の数字(i+1番目)よりも大きければその時点で並び替えは失敗しているので、return Falseという

配列の1つ目から、forで回して、最後の1個以外を一つ後に来る配列の要素と大きさを比べている。 最後の要素までいったということが配列が正しく並び替えられている理由になるので、最後の一個は比較しない。

in_orderがTrueを返すまではランダムに並び替える作業を止めないので、while not文でTrueが返ってくるまでランダムシャッフルと並び替えの確認作業をし続ける。

import random
from typing import list

def in_order(numbers):
    for i in range(len(numbers) - 1):
        if numbers[i] > numbers[i+1]:
            return False
    return True

def bogo_sort(numbers):
    while not in_order(numbers):
        random.shuffle(numbers)
    return numbers

if __name__ == '__main__':
    print(bogo_sort([1, 5, 3, 2, 6]))
    
[1, 2, 3, 5, 6]

in_orderの確認はリスト内包括を利用することで1文で書くことができる。

def in_order(numbers: List[int]) -> bool:
    return all(numbers[i] <= numbers[i + 1] for i in range(len(numbers) - 1))

def bogo_sort(numbers: list) -> list:
    while not in_order(numbers):
        random.shuffle(numbers)
    return numbers

if __name__ == '__main__':
    print(bogo_sort([1, 5, 3, 2, 6]))
def bogo_sort(numbers: List[int) -> List[int]:

と書くことで、引数にlist型を期待していて、返り値にinteger型のlistを返すということを明示できる。 listの代わりにboolなども使用可能。

詳しくはなんかぐぐる実践!!Python型入門(Type Hints)

ランダムな配列を適当に作るコード

0 ~ 100までのランダムな数字で10個の要素を持つ配列を作成する。

if __name__ == '__main__':
    nums = [random.randint(0, 100) for _ in range(10)]
    print(nums)

[21, 97, 13, 36, 89, 59, 30, 50, 14, 15]

このようにbogoソートはランダムで実行するので、基本的に処理時間は長い。運が良ければ処理時間が短くなるが可能性はひくい。下記、ボゴソートを行った時の処理時間を測定。 配列が100個あるときは終わらなかった。。。

# 配列が10この時
[17, 26, 31, 31, 49, 51, 64, 69, 76, 89]
4.3439563389993054

Pythonの if name == 'main': は何のためにあるものですか?

この構文がないと、単にimportされた時にも.pyファイルが実行されてしまうので、import時の実行を防ぐために記載される処理。

データ構造とアルゴリズム:Bubbleソート

一番左側から、配列の個数分forループを行い、limitまで到達したら再度左に戻ってきて同じ処理を行う。 その際にlimitの位置は1つ左に移動する。

スクリーンショット 2020-11-25 0.19.06.png (391.4 kB) スクリーンショット 2020-11-25 0.19.19.png (378.2 kB)

  • for j in range(len_numbers - 1)の部分でlimitの移動を再現している。
    • 一番大きい数字は1週目で一番右にくるようになっているのでlimitを設けて一番右端の数値は処理しなくても良いようにする
    • limitを設けることで、無駄なソート処理を行う必要がないので、コードのパフォーマンスが向上する
  • for文を2回行って2個目のfor分内で一つ前の配列要素(i)とその一つ後の配列要素を比較して左側(i)の値が小さければ右側の値と入れ替える。
  • numbers[j], numbers[j + 1] = numbers[j + 1], numbers[j]という処理で入れ替えを行える。
from typing import List

def bubble_sort(numbers: List[int]) -> List[int]:
    len_numbers = len(numbers)
    for i in range(len_numbers):
        for j in range(len_numbers - 1 - i):
            if numbers[j] > numbers[j + 1]:
                numbers[j], numbers[j + 1] = numbers[j + 1], numbers[j]
    return numbers


if __name__ == '__main__':
    nums = [2, 5, 1, 8, 7, 3]
    print(bubble_sort(nums))
    
[1, 2, 3, 5, 7, 8]

処理時間

bogoソートと比較すると圧倒的に早くなっている。

[1, 2, 4, 5, 6, 8]
0.0003845040009764489

# 配列をランダムに作成したとき
[64, 181, 228, 335, 360, 377, 500, 627, 883, 909]
0.00043242100036877673

ランダムな配列の作り方

これで、0 ~ 1000までのランダムな数字で要素が10個の配列を作ることができる。

import random
arry = [random.randint(0, 1000) for i in range(10)]

CH1:kubernetes基礎 - 基本的な構成と、各種機能について

kubernetes用語集

kubernetes チュートリアル

Docker & kubernetes tutorial YouTube

まずはDoker

#37: AI-人工知能/MLOps/docker/CH1: Docker imagesとVolumeについて

kubernetes

アプリケーションの運用のトレンドがMonolithからMicroservicesに移ってきているので、複数のコンテナを用意してそれらのコンテナをコンテナオーケストレーションツールで操作・運用することで様々な運用環境構築・対応している。

benefits

1. High Availability - アプリの動作が停止することを防止している 2. Scalability - アクセスを分散させて動作させることができるのでアプリの動作やパフォーマンスが高い 3. Disaster recovery - バックアップやリストアが容易にできる

kubernetesアーキテクチャ

スクリーンショット 2020-11-21 20.26.36.png (220.3 kB)

それぞれのworkerではkubeketというものが動いていて、それがそれぞれのworkerノードとデータをやりとりしたり、アクセスを行ったりを可能にしている

Pod, Service & Ingress

kubernetesの基本的な構成要素で、kubernetesを実用的に使うためにはこれらを知っておく必要がある。

スクリーンショット 2020-11-21 20.31.57.png (258.6 kB)

Pod

Podについての説明は公式HPに書いているが、実際に触ってみないとなんとも。。 密接に関連するアプリを起動しているコンテナをカプセル化させてまとめるコンテナのコンテナのようなもののよう。 https://kubernetes.io/ja/docs/concepts/workloads/pods/pod-overview/

スクリーンショット 2020-11-21 23.04.48.png (895.3 kB)

  • Pod内で各アプリケーションごとにIPアドレスが振られており、コンテナがkillされた時に、新しくアプリケーションコンテナが立ち上げられるが、IPアドレスが変更されてしまう。そうなると、今まで接続していたIPアドレスに接続されなくなってしまい困るのでIPアドレスの永続化を行うためにServiceが用いられる。

Service and Ingress

PodとServiceのプロセスは結合されていないので、Podのプロセスが止まってしまってもServiceのプロセスが止まることはないのでIPアドレスの永続化を行える。 各PodはServiceを介してコミュニケーションを行う

スクリーンショット 2020-11-21 23.09.15.png (490.6 kB)

Ingress

クラスター内のServiceに対する外部からのアクセス(主にHTTP)を管理するAPIオブジェクトです。 Ingressは負荷分散、SSL終端、名前ベースの仮想ホスティングの機能を提供します。 引用:公式:Ingress

Config Map and Secret

Config Map

コンテナのアプリケーション名などが変更されたた時に各コンテナの設定を変更してre-buildやre-pushを行う必要があるため、一度アプリを止めて再度構築し直しを行わなければいけない。そのような状況を改善するためにConfig Mapが使われる。

スクリーンショット 2020-11-21 23.15.39.png (569.7 kB)

・例えば、dbのアプリケーション名を変更した時に、Config Mapの名称を変更するだけで、Config Mapから、アプリのロケーションを読み取れるのでわざわざDockerfileなどのアプリ名を変更してre-buildしたりしなくても済む。

スクリーンショット 2020-11-21 23.18.16.png (504.4 kB)

しかし、DBのユーザー名やパスワードなどを変更する際にこのConfigMapに記載することはやめたほうが良い。ユーザー名やパスワードの変更を管理したい際に使われるのがSecretという機能である。

Secret

スクリーンショット 2020-11-21 23.21.28.png (805.0 kB)

Volumes

Dockerコンテナのvolumesと同じようなもので、データベースをローカルで管理できるようにしてPodが落ちた時でもデータの永続化ができるようにするもの

Deployments and Stateful Sets

Deployment

Deoploymentは、Podのコピーを作ることによって、もしnode1のPodが落ちたとしてもload balancerによってnode2のアプリケーションをIPにセットすることで運用ができなくなる状態を防ぐことが可能。

スクリーンショット 2020-11-22 0.23.19.png (1.1 MB)

Stateful Sets

StatefulSetsではDBなどのStatefulなアプリケーションの複製を行うために設定されるもので、データベースが落ちた時にもデータの永続化ができるようにするためのもの。

Minikube and Kubectl

minikubeとは?

実運用する際に動くかテストを行いたい時にローカル環境でミニマムなPod環境を作成してテストを行うことができるツール - ローカルPC上にVirtual Boxを構築することができる - そのVirtual Box上でnodeを走らせることができる - 1 node K8s cluster

スクリーンショット 2020-11-22 0.42.02.png (333.1 kB) スクリーンショット 2020-11-22 0.43.47.png (274.0 kB)

kubuctlとは?

APIを通して、kubernetesの設定をCUIで行えるアプリケーション ローカルマシンにインストールしてterminal上からkubernetesを操作/設定できる スクリーンショット 2020-11-22 0.49.12.png (242.3 kB)

docker/CH1: Docker imagesとVolumeについて

Docker

このページではdockerのimageとvolumeについて捜査を交えながら説明します。 local環境で行うのですが、ローカル環境でdockerを使えるようにしておく必要があります。 もしまだインストールしていなかったら、「docker インストール mac」とかぐぐると色々やり方が出てくるともいます。

(base) y.nakata@MacBook-Pro-4 website % docker -v
Docker version 19.03.13, build 4484c46d9d

### Docker vs VM スクリーンショット 2020-11-21 15.39.36.png (226.9 kB)

Docker benefits

  • コンテナの起動が早い
  • 少ない容量で構築できるので無駄にサーバーのスペースを占有しない
  • モリーの使用率が低い
  • OS全てを使わないので、複数の環境を構築可能

Images

コンテナ操作

nginxのimageをpullする

(base) y.nakata@MacBook-Pro-4 docker_tutorial % docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
852e50cd189d: Pull complete 
a29b129f4109: Pull complete 
b3ddf1fa5595: Pull complete 
c5df295936d3: Pull complete 
232bf38931fc: Pull complete 
Digest: sha256:c3a1592d2b6d275bef4087573355827b200b00ffc2d9849890a4f3aa2128c4ae
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest

Dockerのコンテナを立てる前にどのようなコンテナの中身にするかの設計が書かれているimageをdcoker hubよりダウンロードしてくる。

Docker Hub 色々なアプリケーションのimageがあるので使いたいものをpullして、対象のアプリケーションコンテナを構築することでそのアプリケーションが使えるようになる。

pullしてきたimageを確認する

(base) y.nakata@MacBook-Pro-4 docker_tutorial % docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               latest              daee903b4e43        2 days ago          133MB

コンテナを建てる

(base) y.nakata@MacBook-Pro-4 docker_tutorial % docker run nginx:latest
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Configuration complete; ready for start up

コンテナを確認

(base) y.nakata@MacBook-Pro-4 docker_tutorial % docker container ls
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
db548a38af4d        nginx:latest        "/docker-entrypoint.…"   49 seconds ago      Up 48 seconds       80/tcp              silly_lewin

Portを開く

(base) y.nakata@MacBook-Pro-4 docker_tutorial % docker run -d -p 8080:80 nginx:latest
22cf87a188980192a7771371c1c174202dbd3b530d98580a534f705541c4a71e

というコマンドを打つことで、localhostの8080ポートとコンテナの80ポートを接続できるようにしている。

この後にウェブブラウザでlocalhost:8080に接続するとコンテナのnginxに接続することができる。 スクリーンショット 2020-11-21 17.09.27.png (760.0 kB)

もちろん、8080以外も接続できるので、

(base) y.nakata@MacBook-Pro-4 docker_tutorial % docker run -d -p 3000:80 nginx:latest
22cf87a188980192a7771371c1c174202dbd3b530d98580a534f705541c4a71e

というコマンドでもOK

Volumesについて

スクリーンショット 2020-11-21 17.19.28.png (133.6 kB)

コンテナとホスト(ローカルPC)間のデータの共有を可能にするために使用する スクリーンショット 2020-11-21 17.21.01.png (161.5 kB)

nginx (docker hub): https://hub.docker.com/_/nginx

共有しているvolumeでhtmlファイルを表示させる

スクリーンショット 2020-11-21 17.40.48.png (192.9 kB)

(base) y.nakata@MacBook-Pro-4 docker_tutorial % docker run --name website -d -p 8080:80 nginx    
b86b995e912390fda2885ef65c89316d3ec4d80fb1cc1642a195351e16c8f7eb

imageの時と同様にlocalhostの8080とdockerコンテナの80ポートを接続する.

その後、websitelocalhost:8080に接続できるかを確認する。 スクリーンショット 2020-11-21 17.43.38.png (759.9 kB)

docker stopで一旦コンテナを止める

(base) y.nakata@MacBook-Pro-4 docker_tutorial % docker stop website 
website

Desktopに~/Desktop/website/index.htmlというhtmlファイルを作成する 中身は適当。

<h1> hello docker html </h1>
(base) y.nakata@MacBook-Pro-4 website % docker run --name website -v $(pwd):/usr/share/nginx/html:ro -d -p 8080:80 nginx

というコマンドで、-vでvolumをどこにマウントするかを指定して、pwdwebsiteであることを教えてあげる。

多分これでも良い。

(base) y.nakata@MacBook-Pro-4 website % docker run --name website -v ~/Desktop/website/index.html:/usr/share/nginx/html:ro -d -p 8080:80 nginx

この、/usr/share/nginx/html:roというのはdocker hubのnginxの公式READMEに書いてある。 (https://hub.docker.com/_/nginx ここの、Hosting some simple static contentというタイトルのところ)

:roというのはread onlyでファイルを共有する(マウントする)というのを指定している。 ・そのため、コンテナ内でtouchコマンドを使うことができない。 ・:roを外すと、read onlyでない状態でコンテナを起動できる。

表示する

コンテナを起動

(base) y.nakata@MacBook-Pro-4 website % docker run --name website -v $(pwd):/usr/share/nginx/html:ro -d -p 8080:80 nginx
1f6aab1df9e5566a817629ee9b7da93f00b4231772b6ece5d65e2599a4b26c06

すると、このようにhtmlファイルが表示される

スクリーンショット 2020-11-21 17.50.44.png (707.2 kB)

dockerコンテナを起動したまま、変更を加えても変更が反映されるようになる。 スクリーンショット 2020-11-21 17.51.29.png (712.1 kB)

dockerのコンテナ中で作業する

(base) y.nakata@MacBook-Pro-4 website % docker exec -it website bash
root@1f6aab1df9e5:/# ls
bin  boot  dev  docker-entrypoint.d  docker-entrypoint.sh  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@1f6aab1df9e5:/# ls -al
total 88
drwxr-xr-x   1 root root 4096 Nov 21 08:50 .
drwxr-xr-x   1 root root 4096 Nov 21 08:50 ..
-rwxr-xr-x   1 root root    0 Nov 21 08:50 .dockerenv
drwxr-xr-x   2 root root 4096 Nov 17 00:00 bin
drwxr-xr-x   2 root root 4096 Sep 19 21:39 boot
drwxr-xr-x   5 root root  340 Nov 21 08:50 dev
drwxr-xr-x   1 root root 4096 Nov 18 07:48 docker-entrypoint.d
-rwxrwxr-x   1 root root 1202 Nov 18 07:47 docker-entrypoint.sh
drwxr-xr-x   1 root root 4096 Nov 21 08:50 etc
drwxr-xr-x   2 root root 4096 Sep 19 21:39 home
drwxr-xr-x   1 root root 4096 Nov 18 07:48 lib
drwxr-xr-x   2 root root 4096 Nov 17 00:00 lib64
drwxr-xr-x   2 root root 4096 Nov 17 00:00 media
drwxr-xr-x   2 root root 4096 Nov 17 00:00 mnt
drwxr-xr-x   2 root root 4096 Nov 17 00:00 opt
dr-xr-xr-x 130 root root    0 Nov 21 08:50 proc
drwx------   2 root root 4096 Nov 17 00:00 root
drwxr-xr-x   1 root root 4096 Nov 21 08:50 run
drwxr-xr-x   2 root root 4096 Nov 17 00:00 sbin
drwxr-xr-x   2 root root 4096 Nov 17 00:00 srv
dr-xr-xr-x  13 root root    0 Nov 21 08:50 sys
drwxrwxrwt   1 root root 4096 Nov 18 07:48 tmp
drwxr-xr-x   1 root root 4096 Nov 17 00:00 usr
drwxr-xr-x   1 root root 4096 Nov 17 00:00 var

bootstrap のページを表示する

Bootstrap One Page Templates https://bootstrapmade.com/bootstrap-one-page-templates/

このサイトから好きなものを選んで、ソースをダウンロードしてくる。 今回はこれ。 スクリーンショット 2020-11-21 19.17.15.png (826.7 kB)

ファイル: Lonely.zip (4.2 MB)

website配下に中身をコピーする。

(base) y.nakata@MacBook-Pro-4 website % ls
Readme.txt      assets          changelog.txt       forms           index.html      inner-page.html     portfolio-details.html
(base) y.nakata@MacBook-Pro-4 website % pwd
/Users/y.nakata/Desktop/website

すると、index.htmlを表示するはず。。。

(base) y.nakata@MacBook-Pro-4 website % docker run --name website -v $(pwd):/usr/share/nginx/html:ro -d -p 8080:80 nginx
63af065d9ce329df04a2fbc0df8f61de393bca7bfcea666a4a7bf36de268aeef

見事ページが表示されました! スクリーンショット 2020-11-21 19.21.43.png (5.1 MB)