エクセルVBA オブジェクト指向備忘録クラス003延長(ユーザーフォームでの利用)

20240204エクセルVBA オブジェクト指向備忘録クラス003延長(ユーザーフォームでの利用)


エクセルVBA オブジェクト指向備忘録

<前書き>
エクセルVBAオブジェクト指向、初心者です。
VBA自体は、以前から使用していました。
オブジェクト指向というものがあることは、知っていましたが、ネットなどを見てもよく分からず、挫折した過去あり。

エクセルVBAで、オブジェクト指向を必要とすることもなかったので、諦めていましたが、
youtubeで、「ひとりごとワンダーランド」様のエクセルVBAでのクラスに関する動画を見させていただき、
少しだけやる気になっています。感謝。
(まだ、動画は最後まで見ていません。汗)
<以上前書き>


前回
youtube「ひとりごとワンダーランド」様のクラスモジュールの作法(なるべくprivateでpublicを減らすとか、クラス内変数の書き方とか)を使って、ネットHPで「いつも隣にITのお仕事」様の記事「エクセルVBAでエクセル表のデータを反映するメソッドとクラスを使うメリット」をコード化しました。
分かっていないので、間違っているかも。(多分、間違っている。汗)
注:もしこのブログ記事に関し、youtube「ひとりごとワンダーランド」様、ネットHP「いつも隣にITのお仕事」様におかれまして、不都合があり、削除すべき場合は、即削除いたします。


前回に引き続き、以下自分用のメモ。


今回
「いつも隣にITのお仕事」の記事に、ちらっと「ユーザーフォームで扱えるようにすると・・・」と書いてありました。
それをやってみました。
このようなユーザーフォームを用意。

 

 

最初、昔ながらに、Private Sub UserForm_Initialize()に、


dim a_row as long
a_row =  Cells(Rows.Count, 1).End(xlUp).Row


で、書き始めたのですが、そもそもクラスpersonsでItemsコレクションを取得するので、こんなやり方ではないのだろうと、
BingAI様に何回か質問して、下記のコードになりました。
(エラー処理は、ほぼ実装してないです。)
注:以下、BingAI様にほぼ作成いただきました。不都合あれば削除します。

前回の記事のクラス(2)(3)を使います。((1)の標準モジュールMySubは使ってません。)


/////////////////////////////////////
(4)ユーザーフォーム
Private Sub UserForm_Initialize()

    ' Personsクラスのインスタンスを作成
    Dim vPersons As Persons
    Set vPersons = New Persons

    ' スクロールバーの最小値と最大値を設定
    With ScrollBar1
        .Min = 1
        On Error GoTo ErrorHandler
        .Max = vPersons.Items.Count
        On Error GoTo 0
    End With

    ' 初期表示
    Call ShowPerson(1)

    Exit Sub

ErrorHandler:
    MsgBox "エラーが発生しました。PersonsクラスのItemsが存在しない可能性があります。", vbCritical
End Sub

Private Sub ScrollBar1_Change()

    ' スクロールバーの値に対応するPersonを表示
    Call ShowPerson(ScrollBar1.Value)

End Sub

Private Sub ShowPerson(index As Integer)

    ' Personsクラスのインスタンスを作成
    Dim vPersons As Persons
    Set vPersons = New Persons

    ' Personを取得
    Dim person As person
    Set person = vPersons.Item(index)

    ' テキストボックスに表示
    TextBox1.Text = person.id
    TextBox2.Text = person.FirstName
    TextBox3.Text = person.Gender
    TextBox4.Text = Format(person.Birthday, "yyyy/mm/dd")

End Sub

Private Sub CommandButton1_Click()

    ' テキストボックスの値をチェック
    If TextBox1.Text = "" Or TextBox2.Text = "" Or TextBox3.Text = "" Or TextBox4.Text = "" Then
        MsgBox "全てのテキストボックスに値を入力してください。", vbExclamation
        Exit Sub
    End If

    ' Personsクラスのインスタンスを作成
    Dim vPersons As Persons
    Set vPersons = New Persons

    ' 新しいPersonを追加
    Dim values As Variant
    values = Array(TextBox1.Text, TextBox2.Text, TextBox3.Text, CDate(TextBox4.Text))
    Call vPersons.Add(values)

    ' スクロールバーの最大値を更新
    ScrollBar1.Max = vPersons.Items.Count

    ' エクセルシートに反映
    Call vPersons.ApplyToSheet

End Sub

Private Sub CommandButton2_Click()

    ' テキストボックスからIDを取得
    Dim id As String
    id = TextBox1.Text
    
    ' Personsクラスのインスタンスを取得
    Dim vPersons As Persons
    Set vPersons = New Persons
    
    ' 指定されたIDのデータを削除
    vPersons.Remove id
    
    ' スクロールバーの最大値を1減らす
    ScrollBar1.Max = ScrollBar1.Max - 1
    
    ' エクセルシートから該当のデータを削除
    Dim rng As Range
    Set rng = Sheet1.Columns(1).Find(id)
    If Not rng Is Nothing Then
        rng.EntireRow.Delete
    End If

    ' エクセルシートに反映
    Call vPersons.ApplyToSheet

End Sub

Private Sub CommandButton3_Click()

    ' テキストボックスからIDを取得
    Dim id As String
    id = TextBox1.Text
    
    ' Personsクラスのインスタンスを取得
    Dim vPersons As Persons
    Set vPersons = New Persons
    
    ' 指定されたIDのデータを取得
    Dim person As person
    Set person = vPersons.Item(id)
    
    ' テキストボックスのデータで上書き
    person.FirstName = TextBox2.Text
    person.Gender = TextBox3.Text
    person.Birthday = CDate(TextBox4.Text)
    
    ' エクセルシートに反映
    Call vPersons.ApplyToSheet

End Sub

////////////////////////////////////////


感想:
クラスで作ったものが、うまく使えれば、手続き型(上から下処理)のサブルーチンよりも使い勝手がいいのかもしれない。
サブルーチンは、一つの機能全体(それだけで一応のプログラムのまとまり)だけど、
クラスは部品のイメージなのか(部品をその箇所・箇所で組み立てて使う?)

まだ、全く分かってません。汗。

 

エクセルVBA オブジェクト指向備忘録クラス002

20240203エクセルVBA オブジェクト指向備忘録クラス002
エクセルVBA オブジェクト指向備忘録
 
<前書き>
エクセルVBAオブジェクト指向、初心者です。
VBA自体は、以前から使用していました。
オブジェクト指向というものがあることは、知っていましたが、ネットなどを見てもよく分からず、挫折した過去あり。
 
エクセルVBAで、オブジェクト指向を必要とすることもなかったので、諦めていましたが、
youtubeで、「ひとりごとワンダーランド」様のエクセルVBAでのクラスに関する動画を見させていただき、
少しだけやる気になっています。感謝。
(まだ、動画は最後まで見ていません。汗)
<以上前書き>
 
 
前回に引き続き、以下自分用のメモ。
 
 
youtube「ひとりごとワンダーランド」様のクラスモジュールの作法(なるべくprivateでpublicを減らすとか、クラス内変数の書き方とか)を
使って、ネットHPで「いつも隣にITのお仕事」様の記事「エクセルVBAでエクセル表のデータを反映するメソッドとクラスを使うメリット」を
コード化しました。
分かっていないので、間違っているかも。(多分、間違っている。汗)
注:もしこのブログ記事に関し、youtube「ひとりごとワンダーランド」様、ネットHP「いつも隣にITのお仕事」様におかれまして、不都合があり、削除すべき場合は、即削除いたします。
 
コードの内容は、エクセルシート上のデータに対し、モジュールから削除や追加、修正を行うものです。
(自分のコメントも少し入ってます。)
 
////////////////////////////
(1)標準モジュール
Sub Mysub()
    Dim vPersons As Persons  '独自クラス
    Set vPersons = New Persons 'クラス生成 先にvPersons生成(Class_Initialize()動く)
    
    
    With vPersons
'データ追加
        .Add (Array("a04", "Jay", "male", #7/7/1995#))
        'データ削除
        .Remove 2
        'データ修正
        With .Item("a01")
            .FirstName = "Bomb"
            .Birthday = #11/11/1993#
        End With
        'エクセルシートに新規書き換え
        .ApplyToSheet
    End With
End Sub
 
 
 
 
///////////////////////////////////
(2)クラス「Person」
'privateで作る・・・もしかして、書き換えが必要な項目はpublicでいい?(取り出すのにgetなしでいいから・・・)
Private mId As String
Private mFirstName As String
Private mGender As String
Private mBirthday As Date
 
Public Sub Initialize(values As Variant) 
 'クラスinitializeではなくメソッドで初期化 
'(VBAのクラスinitializeは、(コンストラクタ)引数持てないらしい。定数?)
                                    
    Select Case TypeName(values)
        Case "Range"
            mId = values(1).Value
            mFirstName = values(2).Value
            mGender = values(3).Value
            mBirthday = values(4).Value
        Case "Variant()"                '"Variantはダメ"
            mId = values(0)
            mFirstName = values(1)
            mGender = values(2)
            mBirthday = values(3)
    End Select
End Sub
 
Property Get Id() As String  '省略するとpublic 'privateだとエラー
    Id = mId      '反対になる
End Property
 
Property Get FirstName() As String   
    FirstName = mFirstName   
End Property
 
 
Property Get Gender() As String   
    Gender = mGender    
End Property
 
 
Property Get Birthday() As Date   
    Birthday = mBirthday    
End Property
 
 
Property Get IsMale() As Boolean
    IsMale = (mGender = "male")
End Property
 
 
Property Let Id(pId As String)
    If mId <> "" Then
        Debug.Print "IDは上書き不可"
    Else
         mId = pId
    End If
End Property
 
 
Property Let FirstName(pFirstName As String)
     mFirstName = pFirstName
End Property
 
 
Property Let Gender(pGender As String)
     mGender = pGender
End Property
 
Property Let Birthday(pBirthday As Date)
     mBirthday = pBirthday
End Property
 
 
 
 
////////////////////////////////////////
(3)クラス「Persons」
Private mItems As Collection   'privateにする
 
Private Sub Class_Initialize()
    Set mItems = New Collection
    
    With Sheet1
        Dim i As Long
        i = 2
        Do While .Cells(i, 1).Value <> ""
 
            Me.Add .Range(.Cells(i, 1), .Cells(i, 4))
            
            i = i + 1
        Loop
   End With
End Sub
 
 
Property Set Items(pItems As Collection)
    Set mItems = pItems
End Property
 
'シンプルにaddメソッド追加を直し
Function Add(values As Variant) As person
    Dim mPerson As person
    Set mPerson = New person  'perosnクラスをインスタンス
 
    mPerson.Initialize values
    
    mItems.Add mPerson, mPerson.Id   
    
    Set Add = mPerson
End Function    
 
 
Property Get Items() As Collection
    Set Items = mItems
End Property
 
Property Get Item(key As Variant) As person
    Set Item = mItems.Item(key)
End Property
 
 
Sub Remove(key As Variant)
    mItems.Remove key
End Sub
 
 
Sub ApplyToSheet()
    With Sheet1
        .Cells.Clear
        .Range(.Cells(1, 1), .Cells(1, 4)) = Array("Id", "FirstName", "Gender", "Birthday")
       
        Dim i As Long: i = 2
        Dim mPerson As person
        For Each mPerson In mItems
            .Range(.Cells(i, 1), .Cells(i, 4)) = Array(mPerson.Id, mPerson.FirstName, mPerson.Gender, mPerson.Birthday)
            i = i + 1
        Next mPerson
    End With
End Sub
 
**********************************************
主に、2と3のクラスで、privateを多くしたのが、工夫点かもしれません。
(スコープ「public」と「private」についての使い方)
 
そのために、クラスがごちゃごちゃしました。
(きちんとした使い方なのか、後から考えてみます。)
 
その他、書き方ですが、手続き型(プロシージャ型)は、主に上から下へ、書いていく感じ(あまり削除しない)ですが、
クラスは、クラスと標準モジュールを行ったり来たり。
以前書いたものを、ばっさり削ったり、どんどん変わっていく(クラスに機能を追加したり、移すから?)感じがします。
 
(あと、クラスにprivateでメンバ変数を使うと、コード実行中に扱う変数の数がすごく多くなるのが気になりました。)
 
素人なので、分かりませんが。
 
 
追記
「いつも隣にITのお仕事」の記事に、「ユーザーフォームで扱えるようにすると・・・」と書いてありました。
できたら、標準モジュールに書いた値・命令などをユーザーフォームで、入力・実行できるといいな。

エクセルVBA オブジェクト指向備忘録クラス001(クラスの書き方の比較)

20240122エクセルVBA オブジェクト指向備忘録クラス001


エクセルVBA オブジェクト指向備忘録(クラスの書き方の比較)

エクセルVBAオブジェクト指向、初心者です。
VBA自体は、以前から使用していました。
オブジェクト指向というものがあることは、知っていましたが、ネットなどを見てもよく分からず、挫折した過去あり。

エクセルVBAで、オブジェクト指向を必要とすることもなかったので、諦めていましたが、
youtubeで、「ひとりごとワンダーランド」様のエクセルVBAでのクラスに関する動画を見させていただき、
少しだけやる気になっています。感謝。
(まだ、動画は最後まで見ていません。汗)


で、「ひとりごとワンダーランド」様が強調していることの一つに、スコープ「public」と「private」についての使い方がありました。

よく変数の宣言に、publicを使っているものが散見されるが、privateがいいのではないかとの意見。
そうしないと、変数がどこからでも書き換えられて、クラスにした意味(意義)が半減するような指摘がありました。
カプセル化したのに、意味がない。)


で、並行して、ネットHPで「いつも隣にITのお仕事」様も見ている。
(これも途中までしか見てません。汗)
(注:まだ途中です。最後まで読んだら、もしかして、ここに書いた内容(捉え方・考え方)が変わるかもしれません。)(自分用メモなのでご容赦下さい。)

 

愚弟的には、「いつも隣にITのお仕事」様の方は、「エクセルVBAでクラスモジュールを使って独自のコレクションを作る方法」まで見ています。
そこでは、下記のように、プログラムを書いています。
(もし不都合ありましたら、削除致します。)
一部、private変数(Id)もありますが、基本的にpublic変数を使用しています。
(注:このページは、独自のコレクションを使うと書いてあるように、初心者には、理解がややこしいトコです。クラスを新たに作ってその中にコレクションを置く・・・。)


標準モジュール//////////////////////①
Sub Mysub()

    Dim myPersons As Persons
    Set myPersons = New Persons
    Set myPersons.Items = New Collection   

    With Sheet1
    
        Dim i As Long
        i = 2
        
        Do While .Cells(i, 1).Value <> ""
            Dim p As person       
            Set p = New person
            
            p.Initialize .Range(.Cells(i, 1), .Cells(i, 4))
            myPersons.Items.Add p, p.Id

            i = i + 1
        Loop
        
    End With

    Stop
    
End Sub


クラスPerson///////////////////////②(②は今回のテーマとは関係ありません)
Private Id_ As String   'privateにしている。他の変数はpublic

Public FirstName As String

Public Gender As String

Public Birthday As Date

Public Sub Initialize(ByVal rng As Range)

    Id_ = rng(1).Value
    FirstName = rng(2).Value
    Gender = rng(3).Value
    Birthday = rng(4).Value

End Sub

Public Property Let Id(ByVal newId As String)
    If Id_ <> "" Then                                'もしif文なければ、何回もアクセス可能
        Debug.Print "Idは上書きすることはできません"
    Else
        Id_ = newId
    End If
End Property

Public Property Get Id() As String

    Id = Id_

End Property

 

クラスPersons/////////////////////////////③
Public Items As Collection

 

①②③の構成になっている。特に③にpublicを使っている。
なお、「いつも隣にITのお仕事」様は、お作法として、クラス内のprivate変数は、「Id_」のように、後ろにアンダーバーを入れています。
インスタンスに使う変数はpなどでシンプルです。

これだけで、クラスPersonsのItemsがコレクションとして使用可能になっている。※
(※この章では、コレクションを新たなクラス(クラス②)で作って、オブジェクトとして使用するというややこしいことをしています。)

 


**********************************************************
上記を、「ひとりごとワンダーランド」様のprivate変数を多用したパターンに書き換える。
(自分で考えたので、間違っていたらスミマセン。)

標準モジュール//////////////////////①
Sub Mysub()
    
    Dim vPersons As Persons  '独自クラス
    Set vPersons = New Persons 'クラス生成
   
    With Sheet1
        Dim i As Long
        i = 2
        Do While .Cells(i, 1).Value <> ""
            Dim vPerson As person
            Set vPerson = New person  '毎回セット
            vPerson.Initialize .Range(.Cells(i, 1), .Cells(i, 4))
            
            vPersons.Items.Add vPerson, vPerson.Id    
            
            i = i + 1
        Loop
   End With

    Stop
End Sub


クラスPerson///////////////////////②(②は今回のテーマとは関係ありません)
Private mId As String
Private mFirstName As String
Private mGender As String
Private mBirthday As Date

Public Sub Initialize(rng As Range)  'クラスinitializeではなくメソッドで初期化
                                    '(VBAのクラスinitializeは、(コンストラクタ)引数持てないらしい?)
    mId = rng(1).Value
    mFirstName = rng(2).Value
    mGender = rng(3).Value
    mBirthday = rng(4).Value

End Sub


Property Get Id() As String  

    Id = mId      

End Property

Property Get FirstName() As String    
    FirstName = mFirstName    
End Property


Property Get Gender() As String   

    Gender = mGender     

End Property


Property Get Birthday() As Date   

    Birthday = mBirthday    

End Property

 

 

Property Let Id(pId As String)

    If mId <> "" Then
        Debug.Print "IDは上書き不可"
    Else
         mId = pId
    End If

End Property


Property Let FirstName(pFirstName As String)

     mFirstName = pFirstName

End Property


Property Let Gender(pGender As String)

     mGender = pGender

End Property

Property Let Birthday(pBirthday As Date)

     mBirthday = pBirthday

End Property

 

 

クラスPersons/////////////////////////////③
Private mItems As Collection   'privateにする

Private Sub Class_Initialize()
    Set mItems = New Collection
End Sub


Property Set Items(pItems As Collection)
    Set mItems = pItems
End Property


Property Get Items() As Collection
    Set Items = mItems
End Property

**********************************************************
上記が、「ひとりごとワンダーランド」様風のprivate変数を多用したパターン。
(違っていたらすみません。)
「ひとりごとワンダーランド」様は、お作法として、基本的に、標準モジュールの変数は、
Set vPersons = New Personsのように、vを付ける。

また、クラス内変数等は、
Property Let Id(pId As String)
         mId = pId
End Property
のように、渡ってくる変数にはp、
クラス内変数は、mを付けている。

で、通常、変数をprivateでやり取りしようとすると、
letやgetが必要だが、
今回は、クラス内で、コレクションを扱うため、
setやget以外に、
Private Sub Class_Initialize()
    Set mItems = New Collection
End Sub
というように、Class_initializeで、コレクションの定義を行った。

 

で、いいのかな・・・。汗

 

追加メモ:(間違っているかも)
propertyは、関数のようなものなのだろう。
mainでクラスが作られて、呼ばれれば必ずそこを通る。
関数っぽいので色んなところから呼ばれても、if文などで、書き換えに制限を加えることができる。

 

今まで自分は、「手続き型」のコードしか書いてこなかったので、クラスには違和感あるし、今まで作ってきたものをリファクタリングするほど、手慣れることもなさそうだが、違った発想に感じられるので、面白い気もします・・・汗。

 

追加メモ:(間違っているかも)
propertyは、関数のようなものなのだろう。

mainでクラスが作られて、呼ばれれば必ずそこを通る。
関数っぽいので色んなところから呼ばれても、if文などで、書き換えに制限を加えることができる。

 

備忘録(その他)( docker compose ymlファイル)

20240107Docker備忘録(その他)( docker compose ymlファイル)

こちらは、パソコン素人です。
Docker素人です。
以下違いだらけです。自分用メモ。

(もし、投稿内容(引用等)に不具合がありましたら、削除いたしますので、ご指摘下さい。)

 

「Docker」というものがあるらしい。
ウィキペディアを見たが、よくわからない。

 

*************************************************
前回まで・・・
youtube「だれでもエンジニア」様のをまねてみる。(感謝)

docker エンジンの起動など(localPCで表示など)
*************************************************

 

今回は、別のyoutube徳田啓様の「Docker 最初の一歩」を視聴したのものの自分用メモ。
(素人なので、自信なし。汗)

動画の前半は、インストールなどの説明。

後半は、Docker Composeを使用したlocalPCでの表示など。

 

***********************************************前置き
ネットで検索すると、 Docker Composeとは
「複数のコンテナを定義し実行する Docker アプリケーションのためのツール
YAMLファイルを使い、アプリケーションのサービスを設定し、コマンドを1つ実行するだけで、設定内容に基づいた全てのサービスを生成・起動」
とのことです。
************************************************


「だれでもエンジニア様」で勉強した前回までのは、dockerエンジンの使い方で、dockerfileを用いた1個のアプリ開発と考えて良さそう。

今回の徳田啓様の「Docker 最初の一歩」は、複数のアプリ開発を並行して進めるためのやり方のようです。
そのためには、docker composeを使用。(ymlファイルは、当該サーバー用の設定ファイルのようです。)


****************************************
注:docker composeでは、DockerFileは不要なのか?
docker-compose.ymlファイルで直接イメージを指定すれば、Docker Composeでコンテナを起動するためのDockerfileは必要ないですが、
既存のイメージに対して追加の設定やカスタマイズを行いたい場合は、Dockerfileを作成し、それをdocker-compose.ymlから参照します。
引用元Qiita
(ごん)様
Docker Composeについてざっくり理解する【概要 / ymlファイル書き方 / コマンド操作】(感謝いたします)
****************************************

 

で、後半の内容:docker composeを使用した方法ですが、
まず、デスクトップなどに、作業用フォルダを作ります(SAMPLE-PROJECT)。
それをVSコードにドロップします。
その中に、フォルダを作ります(web)。
その中に、index.phpファイルを作ります。
ファイルの内容
<?php
phpinfo();
(PHPの設定情報を表示するらしいです。)

 

で、もう一つymlファイル(docker-compose.yml)を入手して、
上記のwebファルダと同列にドロップします。
docker-compose.ymlは、徳田啓様の「Docker 最初の一歩」に用意されたGitHubのリンクから入手しました。

 

docker-compose.ymlの内容は、
version: '3.5'とか※、
  php-apache:
  mysql:
  phpmyadmin:
などローカルサーバーの設定でした(多分。汗)。

 

で、docker compose up -d でサーバーを起動します。
(この場合、VSコードで新しいターミナルを開いて、上記コマンドを実行します。)

で、localhost:8080で、PHPの設定情報が表示されたら成功。

(サーバーを止めたければ、docker compose stop だそうです。)

 

※上記のymlファイルのversion: '3.5'は、bingchatによると
Docker Composeファイルのversion: '3.5'は、使用するComposeファイル形式のバージョンを指定しています。
バージョン3.5のComposeファイルは、Docker Engineリリース17.12.0+でサポートされています。
だそうです。使う時は、本当に↑bingchatが正しいか確認します。

 

その他
(「だれでもエンジニア様」で勉強した前回までのは、dockerエンジンの使い方で、dockerfileを用いた1個のアプリ開発と考えて良さそう。と記載しましたが、まだ途中までの視聴です。
この先、docker composeが出てくるのかも。)

20240106Docker備忘録4(コマンド logs exec prune)

20240106Docker備忘録4(logs exec prune)


こちらは、パソコン素人です。
Docker素人です。
以下違いだらけです。自分用メモ。

(もし、投稿内容(引用等)に不具合がありましたら、削除いたしますので、ご指摘下さい。)

「Docker」というものがあるらしい。
ウィキペディアを見たが、よくわからない。

*************************************************
前回まで・・・
youtube「だれでもエンジニア」様のをまねてみる。(感謝)
前回の後半部分:
「Dockerのイメージ作り、コンテナ作成起動をやってみる・・・。」(イメージとコンテナの基本操作)(ウィンドウズでやってます。)
docker image build -t sample/webrick:latest .
とか、
docker container run -p 8000:80 --name webrick sample/webrick:latest
とか
とにかくlocalhost:8000で表示させることに成功した。(と思われる・・・)
*********************************************

 

今回:
前回の続きで、docker containerでよく使うコマンド。
youtube「だれでもエンジニア」様の続きです。感謝します。
windows taeminalで以下を試します。

 

docker container logs webrick
で、localhost:8000ポートへのアクセス状況(時刻)などが分かる。

 

docker container exec webrick ruby -v
で、webrickで使用しているルビーのバージョンを表示させることができる。

 

docker system purune -a
で、使っていないイメージやコンテナを削除できる。

 

ネットでpuruneを見たら、対象はsysytemだけでなく
docker image prune 
(使っていないイメージをクリーンアップ)なども出来るようだ。
sysytemだと、
「ボリュームはデフォルトでは削除されないため、ボリュームを削除するには docker system prune で --volumes フラグを使う必要があります」ということも書いてあり、
ボリュームっていう種類もあるんだなと思いました。
初心者なので分かりません。

 

20240102Docker備忘録3(失敗→できました)

20240102Docker備忘録3(失敗→できました)


こちらは、パソコン素人です。
Docker素人です。
以下違いだらけです。自分用メモ。

(もし、投稿内容(引用等)に不具合がありましたら、削除いたしますので、ご指摘下さい。)

「Docker」というものがあるらしい。
ウィキペディアを見たが、よくわからない。

*************************************************
前回まで・・・
youtubeで解説されている方がおいでたので、試しに見てみました。(「だれでもエンジニア様」他いろんな皆様。感謝いたします。)
「だれでもエンジニア様」のを見ながら、インストール等したみた。
この動画は2021年時点のようで、少しインストール方法など変わっているのかもしれません。
注意。前回失敗しています。

*********************************************

今回:
前回失敗しています・・・からできました。(正しいかは分からない)

今回も上記、「だれでもエンジニア様」のをまねてみる。
前回の後半部分:
「Dockerのイメージ作り、コンテナ作成起動をやってみる・・・。」(イメージとコンテナの基本操作)(ウィンドウズでやってます。)

前回やったこと////////////////////////

(1)main.rb
require 'webrick'
server = WEBrick::HTTPServer.new(
    DocumentRoot: './',
    BindAddress: '0.0.0.0',
    port: 8000
)

server.mount_proc('/') do |req,res|
    res.body = 'hello'
end

server.start

(2)Dockerfile
FROM ruby:2.7

RUN mkdir /var/www
COPY main.rb /var/www

CMD ["ruby","/var/www/main.rb"]


それらを以下のようにイメージ作成、コンテナ起動。(3)(4)

(3)docker image build -t sample/webrick:latest .
※「.」を忘れないこと

(4)docker container run -p 8000:8000 --name webrick sample/webrick:latest

上記(3)(4)はうまくいっているハズ・・・・?


**************************************
これで、ブラウザで「localhost:8000」で、アクセスできるはず・・・。
見ることができない。

このページは現在機能していません。
localhostからデータは送信されませんでした。
ERR_EMPTY_RESPONSE

ERR_CONECTED_REFUSEDの時もあり。


:::::::::::::::::::::::::::::::::::::
今回:いろいろやった。


最初に、(1)で、VSコードを使用する時、documentsというディレクトリでやっていた。ふと、documentsでなく、dockerというディレクトリでないかと思った。
(準備として、上記でする前に、前回試してダメだった
「%USERPROFILE%ディレクトリ(ユーザーホームディレクトリ)に.wslconfigという名前のファイルを作成」を削除した。つまり元の状態にした。)

で、やってみたが、失敗。
VSコードも初心者だが、ディレクトリが違うと、コードが見れたり見れなかったりしたので、そうなのかと思ったのだが。

次に、ふと、「ubuntuでない」のでは?と思った。
YouTubeの画面は、windowsでなくmacだが、ubuntuでないのかもしれない。

そこで、もう一度やり直す。
docker desktopを立ち上げておく。
(今まで、サインインしていなかったが、それも原因かもしれないので、サインインした。他にも使わないイメージはdesktopでdeleteした。)

vsコードでubuntuを使わず、(1)(2)を作成。
(3)(4)もやってみる・・・でもだめだった。


うーん。ふとBingChatに聞いた回答を確認・・・。
ファイアウォールの設定: ファイアウォールがポート8000をブロックしている可能性があります。ファイアウォールの設定を確認し、ポート8000が許可されていることを確認してください。 ・・・ファイヤーウォールウイルス対策ソフトを疑うが、そうでもなさそう。。。


IPアドレスの設定: localhostは自分自身を指すIPアドレスです。もしDockerコンテナが別のマシンで動作している場合、localhostではなく、そのマシンのIPアドレスを使用する必要があります。Dockerコンテナが動作しているマシンのIPアドレスを確認し、http://アドレス>:8000にアクセスしてみてください。 ・・・そうでもなさそう。。。(しかし、多分、これは今回、ある意味正しくてubuntu使用での仮想ではなく、ウインドウズ上でDockerの使用なのだから。)


③省略


④コンテナ内のポート番号: コンテナ内で起動しているアプリケーションが、8000番ポートでリッスンしていることを確認してください。コンテナ内でアプリケーションを起動する際に、正しいポート番号を指定しているかどうかを確認してください。・・・80だった。。。(1)のportを80に。及び(4)の8000:8000を8000:80にしたら、すんなり、edgeでも、chromeでも「localhost:8000」helloの表示が出た。(修正)


何か数年で変わったのか、ウィンドウズだからなのか、自分が分かってないからだろう。

 

20231227Docker的なものの備忘録2(失敗) localhost

20231227Docker的なものの備忘録2(失敗)


こちらは、パソコン素人です。
Docker素人です。
以下違いだらけです。自分用メモ。

(もし、投稿内容(引用等)に不具合がありましたら、削除いたしますので、ご指摘下さい。)

「Docker」というものがあるらしい。
ウィキペディアを見たが、よくわからない。

*************************************************
前回まで・・・
youtubeで解説されている方がおいでたので、試しに見てみました。(「だれでもエンジニア様」他いろんな皆様。感謝いたします。)
「だれでもエンジニア様」のを見ながら、インストール等したみた。
この動画は2021年時点のようで、少しインストール方法など変わっているのかもしれません。
(1)windows terminalを入れる。
(2)vs codeを入れる。
(3)gitを入れる。
(4)WSL2を有効化(してwindows上にlinux環境を構築)
(5)Dockerを入れる。
4,5あたりでつまづくが何とか出来た気がする。(ubuntuが2バージョン(2種類)入ったりしているが・・・汗)
*********************************************

今回:注意。今回失敗しています。(解決方法見つかっていません。)

今回も上記、「だれでもエンジニア様」のをまねてみる。
ubuntuのコマンドの練習からやってみる。
しかし、ubuntuを使うのに、VSコードで開こうとして失敗。
ここでは、windowsterminalでよかった。(使い分けが分かっていない。。。)
上の新しいタグから「ubuntu」を選択し、開く。(自分のPCでは紫の背景色)

コマンドlsとかやってみる。
(lsは、自分のいるディレクトリの中にあるファイルやディレクトリの表示。何も作っていないので、何も表示されないので正解。)

コマンドtouch(新規で空ファイルを作る)をやってみる。ふと気になったのが、「touch tmp」(tmpという空ファイルを作る)だと、「拡張子」はどうするの?ということ。正しいかどうか分からないが、tmpだと拡張子を持たないファイルを作ったことになるようだ。後から拡張子は追加可能らしい。
(↑BingChatに聞きました)

その他、自分で調べたコマンド「rmdir」・・・ディレクトリを削除する(ただし、中にファイルやサブフォルダがあると削除できない)。当該ディレクトリの1個上で使用するようだ。

+++++++++++++++++++++++++++++++++++++++++
次に、Dockerのイメージ作り、コンテナ作成起動をやってみる・・・。(イメージとコンテナの基本操作)

全く、分かっていないが。
クライアントがターミナルでdocker runすると、クライアントからホスト(多分ローカルPC)にタスクが渡される。
ホスト(のデーモン=裏で働くプログラム)が(オンライン上のdokerレジストリから当該イメージを取得し(イメージは先に上げておくようだ))
イメージ作り、コンテナ作成起動すると、runしたものが実行されるらしい。。。。。。。


(1)まず、webアプリのコードを作成(「だれでもエンジニア様」のをまねてみる。)
準備として、windowsterminalでubuntu
コマンドpwdディレクトリの表示。
ディレクトリが何もないので、documents、その下にdockerというフォルダを作った。)
ubuntuwindows ターミナルで)cd documentsで、当該ディレクトリで作業すること。

ターミナル(ububtu)で「code .」と入力。
ファイルアイコンで、ファイルを作成(dockerの下)。

ファイル名「main.rb」
コードは省略します。webrickを使ってウェブサーバーをlocalhostに作成しているようです。
(コード後から出てきます。)

(2)dockerfileを作る。(dockerfileとは、アプリコード、ライブラリ、ベースイメージで「イメージ」を作るものらしい。)
ファイル名「Dockerfile」ファイルを作成(dockerの下)。
コードは省略します。 From ruby:2.7とかRUN mkdir /var/www とか CMDとか
(コード後から出てきます。)

↑main.rbを動かすためのファイルらしいです。

上記までが「イメージを作る準備らしいです。
==========================

やっとイメージ作成「docker imege build」コマンド
ターミナルで、docker imege build -t ・・・・・・・・・(省略)

上記でイメージが作れたかを確認「docker image ls」コマンド

==========================
コンテナを作成して起動「docker container run」コマンド

上記でコンテナが作れたかを確認「docker container ls」コマンド


**************************************
これで、ブラウザで「localhost:8000」で、アクセスできるはず・・・。
見ることができない。

このページは現在機能していません。
localhostからデータは送信されませんでした。
ERR_EMPTY_RESPONSE

ERR_CONECTED_REFUSEDの時もあり。


とりあえず、コードを見直す。/////////////////////見直しとダメなとこ
localhost:8000に送信されないのはなぜ?
wsl2でdockerを使います。
以下のコードをVSコード(ubuntu)で作成。(※ubuntuwindows ターミナルで)cd documentsで、当該ディレクトリで作業すること。)(1)(2) (vsコードは、ターミナルで「code .」で開く。)

(1)main.rb
require 'webrick'
server = WEBrick::HTTPServer.new(
    DocumentRoot: './',
    BindAddress: '0.0.0.0',
    port: 8000
)

server.mount_proc('/') do |req,res|
    res.body = 'hello'
end

server.start

(2)Dockerfile
FROM ruby:2.7

RUN mkdir /var/www
COPY main.rb /var/www

CMD ["ruby","/var/www/main.rb"]


それらを以下のようにイメージ作成、コンテナ起動。(3)(4)

(3)docker image build -t sample/webrick:latest .
※「.」を忘れないこと

(4)docker container run -p 8000:8000 --name webrick sample/webrick:latest

上記(3)(4)はうまくいっているハズ・・・・?
(しかし、1個。注意。実は、ubuntuでdockerのコマンドを入れようとすると最初、エラーになる・・・。で、いつもdocker desktopのsetting WSL integrationを「リフレッシュ」している。)
(wsl2 でdockerを使用しています。VSコードを開いてubuntuで、dockerコマンドを使用しようとすると、毎回最初に
The command 'docker' could not be found in this WSL 2 distro.
We recommend to activate the WSL integration in Docker Desktop settings.
のメッセージが出て、docker desktopのsetting、 Resources、 WSLintegrationのrefreshを行う必要があります。
(Enable integration with additional distros:には、UbuntuUbuntu-20.04があり、Ubuntuを指定しています。))


ダメなとこ:
ブラウザ(edgeもクロームも)で、localhost:8000にアクセスすると、「localhostからデータは送信されませんでした。ERR_EMPTY_RESPONSE」とのメッセージ。

↓↓↓↓↓↓

回避策を探す。
やったこと①ループバックを有効にするってやつをやってみた。
コマンドプロンプトを管理者権限で開き、
CheckNetIsolation LoopbackExempt -a -n=Microsoft.MicrosoftEdge_8weky
と入力。
⇒効果なし

やったこと②WSL2のlocalhostにアクセスするための設定方法を以下に詳しく説明します。
%USERPROFILE%ディレクトリ(ユーザーホームディレクトリ)に.wslconfigという名前のファイルを作成します。
次に、そのファイルに以下の内容を記述します:
[wsl2]
localhostForwarding=True
この設定は、WSL2の共通設定で、localhostForwarding=Trueとすることで、WSL2上で立ち上げたサーバにWindows側からlocalhostで接続できるようになります。
ファイルを保存した後、設定を反映させるためにWSL2を再起動します。再起動は、PowerShell等からwsl --shutdownコマンドを実行することで行えます。
⇒効果なし

やったこと③
高速スタートアップもやめた。
⇒効果なし

やったこと④
ブラウザのクッキーの履歴削除
⇒効果なし

BindAddress: '0.0.0.0',とかがだめなのかとか、考えたが、そうでもなさそう。
WSLだからなのか、自分が悪いのか。