投稿者: sumito.tsukada

  • AWS SAM CLIでDockerがUnreachableな場合の解決

    AWS SAM CLIでDockerがUnreachableな場合の解決

    はじめに

    AWS Serverless Application Model (SAM) は、サーバレスアプリケーションを簡単に作成、テスト、デプロイするためのフレームワークです。しかし、時々 sam build --use-container コマンドを使用したときに、”Docker is unreachable. Docker needs to be running to build inside a container.”というエラーメッセージが表示されることがあります。

    Dockerが実行中であり、Dockerのバージョン情報が正しく表示されているにもかかわらず、このエラーが発生することがあります。このブログでは、その問題の解決法について説明します。

     

    問題の再現

    以下のようなコマンドを実行してみました。

    $ sam build --use-container

    そして、以下のエラーが表示されました。

    Error: Docker is unreachable. Docker needs to be running to build inside a container.

    しかし、Dockerは実行中であり、バージョン情報も正しく表示されます。

    $ docker ps
    CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

    $ docker --version
    Docker version 23.0.5, build bc4487a

    解決法

    解決法は、Dockerのコンテキストを確認し、適切に設定することです。

    まず、現在のDockerのコンテキストを表示します。

    $ docker context ls

    次に、適切なDockerのエンドポイントに対する環境変数 DOCKER_HOST を設定します。

    $ DOCKER_HOST=unix:///Users/sumito.tsukada/.docker/run/docker.sock sam build --use-container

    これにより、Dockerが適切に認識され、SAM buildコマンドが正常に実行されるはずです。

    結論

    DockerとAWS SAM CLIの連携は、サーバレスアプリケーションの開発をスムーズに進める上で非常に便利です。しかし、時々ツール間の接続に問題が生じることがあります。そのような場合は、環境変数を適切に設定し直すことで問題が解決することがあります。ぜひ、この記事があなたの問題解決の一助となることを願っています。

  • ターミナルを開いたら自動でtmuxを起動させる

    ターミナルを開いたら自動でtmuxを起動させる

    はじめに

    tmuxを起動させることを自動化して、新しいターミナルウィンドウを開くと同時にtmuxが起動するように設定する方法を紹介します。

    今回はmacOSのiTerm2を例に説明します。

    ステップバイステップのガイド

    ステップ1: iTerm2を開く

    まずはiTerm2を開きましょう。もしまだインストールしていない場合は、公式サイトからダウンロードしてインストールしてください。

    ステップ2: Preferencesを開く

    次に、上部メニューから「iTerm2」をクリックし、「Preferences」を選択します。またはキーボードショートカットのcommand+,を使用することもできます。

    ステップ3: プロファイル設定を開く

    「Profiles」タブをクリックしてください。左側のプロファイルリストから、使用したいプロファイル(「Default」を使用している方が多いと思います)を選択します。

    ステップ4: コマンド設定を行う

    「General」タブの「Command」セクションに進みます。「Send text at start」にtmuxと入力し、設定を保存します。

    これで設定は完了です。

    ステップ5: 新しいターミナルウィンドウを開く

    新しいターミナルウィンドウ(新しいタブや新しいウィンドウでも構いません)を開いてみましょう。自動的にtmuxが起動するはずです。

    まとめ

    この設定を行うことで、毎回手動でtmuxコマンドを打つ必要がなくなります。

    一度の設定でこれ以降の作業を効率化できるので、ぜひお試しください。

     

     

  • jqを使ったJSONデータの柔軟な操作: ユーザーの属性値の動的変更

    jqを使ったJSONデータの柔軟な操作: ユーザーの属性値の動的変更

    はじめに

    jqはコマンドラインツールで、JSONデータをパースしたり操作したりするのに非常に便利です。今回は、特定のユーザーの属性(タグリスト)から特定の要素を削除する、という具体的なタスクを通じて、jqの使い方について解説します。

    JSONデータの説明

    まずは問題を理解するために、私たちが操作するJSONデータを見てみましょう。以下のような形式のデータです:

    {
    "data": {
    "users": [
    {
    "username": "Alice",
    "tags": "tag1, tag2"
    },
    {
    "username": "Bob",
    "tags": "tag2"
    },
    {
    "username": "Charlie"
    }
    ]
    }
    }

    このデータは、”data”というキーの中に、”users”という配列があります。各ユーザーは”username”と”tags”という2つの属性を持つことができます。

    目標の説明

    ここでの目標は、特定のユーザー(この例では”Alice”)のタグリストから特定のタグ(この例では”tag2″)を削除することです。このようなタスクは、例えば特定のユーザーのロールや権限、ステータスなどを更新する際によく遭遇します。

    jqコマンドの解説

    目標を達成するために、以下のようなjqコマンドを使用します。

    jq -r --arg username "Alice" --arg delete_tag "tag2" '
    .data.users |= map(
    if .username == $username then
    if .tags? | contains($delete_tag) then
    if .tags == $delete_tag then
    del(.tags)
    else
    .tags |= gsub($delete_tag + ", "; "")
    | .tags |= gsub(", " + $delete_tag; "")
    end
    else
    .
    end
    else
    .
    end
    )
    '
    users.json

    ここで”-r”オプションは、出力結果をraw形式(エスケープされていない形式)で出力することを指定します。

    “–arg username “Alice”” と “–arg delete_tag “tag2″” では、コマンド実行時にjqに変数を渡しています。これにより、このコマンドは特定のユーザー名と削除するタグを動的に指定できます。

    そして、”.data.users |= map(…)”では、全てのユーザー(.data.usersの配列)を一つずつ処理しています。この”map”関数は、配列の全ての要素に対して指定した処理(ここでは後続のif文全体)を適用します。

     

    jqコマンドの詳細

    ここで、このjqコマンドがどのように動作しているのかを詳しく見ていきましょう。

    まず、”if .username == $username then”という行では、現在処理しているユーザーのusernameが指定したusernameと一致するかどうかを確認します。もし一致すれば、そのユーザーに対して更なる処理(後続のif文)を行います。

    次に、”if .tags? | contains($delete_tag) then”という行では、現在処理しているユーザーがtags属性を持ち、その中に削除するタグが含まれているかを確認します。ここで、”?”演算子を使うことで、もしユーザーがtags属性を持っていなければエラーにせずにnullを返します。

    そして、もしユーザーが削除するタグだけを持っている場合(つまり、そのユーザーのtagsが削除するタグと全く同じである場合)、”if .tags == $delete_tag then del(.tags)”という部分でそのtags全体を削除します。

    もしユーザーが削除するタグを含むが、他にもタグを持っている場合(つまり、そのユーザーのtagsが削除するタグを含むカンマ区切りの文字列である場合)、

    .tags |= gsub($delete_tag + ", "; "")
    | .tags |= gsub(", " + $delete_tag; "")

    という部分で削除するタグを取り除きます。ここで、”gsub”関数は、第一引数の正規表現にマッチする全ての部分を第二引数に置き換えます。つまり、この行では、タグリストから削除するタグを取り除いています。

    まとめ

    以上が、jqを使ってJSONデータを操作する具体的な例です。この例を通じて、jqの強力さと柔軟性を理解していただけたと思います。JSONデータを操作する必要がある場合、是非jqをお試しください。

  • FlaskとQueueを用いたタスク管理の実装

    FlaskとQueueを用いたタスク管理の実装

    PythonのFlaskフレームワークは、その軽量さと拡張性から、さまざまなウェブアプリケーションで用いられています。今回はFlaskを使用したシステムで、Pythonの組み込みモジュールであるQueueを利用して、タスク管理を効率的に行う方法について解説します。

    この記事で取り扱う主要なテーマは以下の通りです:

    • PythonのQueueを使ったタスク管理
    • Queueとスレッドを組み合わせた非同期処理

    PythonのQueueを使ったタスク管理

    Pythonのqueue モジュールは、FIFO(First-In, First-Out)方式のキューを実装しており、スレッド間でデータの受け渡しを行う際に特に有用です。以下に具体的なコードを示します。

    import queue
    import threading
    # グローバルにキューを作成
    task_queue = queue.Queue()
    def worker():
    while True:
    task = task_queue.get()
    if task is None:
    break
    # ここでタスクを処理
    task_queue.task_done()
    # ワーカースレッドを作成し、実行
    worker_thread = threading.Thread(target=worker)
    worker_thread.start()
    @app.route('/task', methods=['POST'])
    def add_task():
    task_data = request.get_json()
    task_queue.put(task_data)
    return jsonify({'status': 'queued'})

    このコードでは、新たなタスクがPOSTリクエストとして/taskエンドポイントに送信されると、そのタスクはキューに追加されます。一方、バックグラウンドで実行されているワーカースレッドは、キューからタスクを取り出して処理を行います。

    Queueとスレッドを組み合わせた非同期処理

    Queueとスレッドを組み合わせることで、Flaskアプリケーションでの非同期タスク管理を実現できます。これにより、リクエストを迅速に受け付けつつ、時間のかかる処理をバックグラウンドで並行して実行することができます。

    この記事が皆さんのFlaskとPythonのプロジェクトに役立つことを願っています

  • FlaskとThreadを使った並行処理と排他制御の実装

    FlaskとThreadを使った並行処理と排他制御の実装

    PythonのFlaskフレームワークは、小規模なアプリケーションから大規模なエンタープライズアプリケーションまで幅広い用途で使用されています。今回は、Flaskを用いたウェブアプリケーションで、複数のリクエストが同時に来た場合でも、裏側で動く処理を1つに制限する方法を解説します。

    この記事で取り扱う主要なテーマは以下の通りです:

    • Pythonのスレッドを使った並行処理
    • 排他制御によるリソースへの同時アクセス制限

    スレッドを使った並行処理

    Python の threadingモジュールを用いることで、スレッドを利用した並行処理を実装することができます。以下に具体的なコードを示します。

    import threading
    # スレッドを使う処理は関数にまとめます
    def process_request(request_data):
    # リクエストに対する処理を記述
    pass
    @app.route('/exec', methods=['POST'])
    def exec():
    # POSTリクエストのデータを取得
    request_data = request.get_json()
    # 新たなスレッドを作成して関数を実行
    thread = threading.Thread(target=process_request, args=(request_data,))
    thread.start()
    # レスポンスを即時に返す
    return jsonify({'status': 'processing'})

    このコードでは、POSTリクエストが/execエンドポイントに送信されると、新たなスレッドが作成され、process_request関数がそのスレッド上で実行されます。この関数はリクエストのデータを処理し、その間、メインスレッドは次のリクエストを受け付ける準備をします。

    排他制御による同時アクセス制限

    一方、裏側で動く処理を1つに保つためには排他制御が必要です。PythonのthreadingモジュールのLockを用いることで、排他制御を実現できます。以下に具体的なコードを示します。

    lock = threading.Lock()
    def process_request(request_data):
    with lock:
    # リクエストに対する処理を記述
    pass

    このコードでは、lockオブジェクトを用いてwithステートメントの中の処理が排他的に実行されるようになります。すなわち、一度に一つのスレッドだけがこの処理を実行でき、他のスレッドはロックが解放されるまで待機する必要があります。

    これらの方法を組み合わせることで、Flaskでの並行リクエストの受け付けと裏側での処理の排他制御を実現することができます。これにより、アプリケーションのパフォーマンスと安定性を向上させることが可能になります。

    この記事が皆様のPythonとFlaskのプロジェクトに役立つことを願っています。

  • PostgreSQLのテーブル定義を確認する方法:コマンドラインとGUIクライアントの違い

    PostgreSQLのテーブル定義を確認する方法:コマンドラインとGUIクライアントの違い

    PostgreSQLデータベースを操作する際、テーブルの定義を確認する必要がしばしばあります。

    テーブルの列名やデータ型を把握することで、適切なSQLクエリを作成し、データ操作を正確に行うことができます。

    一般的に、PostgreSQLのコマンドラインツールであるpsqlを使用してテーブルの定義を確認することが多いです。コマンドは、指定したテーブルの列名、データ型、修飾子、そして列の説明を表示します。

    例えば、テーブル名がhoge_tableの場合、次のコマンドを使用します:

    \d hoge_table

    しかしながら、全てのデータベース操作がコマンドラインから行われるわけではありません。

    GUIベースのデータベースクライアントツールを使用することが一般的であり、その中でもTablePlusはその使いやすさと直感的なインターフェースで高く評価されています。

    しかし、TablePlusやその他のいくつかのGUIクライアントツールでは、psql特有の\dコマンドが使用できません。

    その場合、次のSQLクエリを使用してテーブルの構造を確認することができます

    SELECT column_name, data_type
    FROM information_schema.columns
    WHERE table_name = 'hoge_table';

    このクエリは、テーブルのすべてのカラム名とそのデータ型を表示します。この方法は標準的なSQLクエリであるため、多くのデータベース管理ツールで使用できます。

    データベースを操作する際には、使用しているツールの特性を理解し、それに応じた最適な操作方法を選択することが重要です。それによって効率的かつ正確なデータ操作を行うことが可能となります。この記事がその一助となれば幸いです。

  • ターミナル操作の効率化:cdコマンドを使った直前のディレクトリへの素早い移動方法

    ターミナル操作の効率化:cdコマンドを使った直前のディレクトリへの素早い移動方法

    はじめに

    日々の開発作業でコマンドラインからファイルシステムを操作することは非常に一般的です。ディレクトリを行き来する際、完全なパスを何度も入力したり、タブ補完を使ってパスを探すのは時間の無駄ですよね。この記事では、ZshやBashなどのシェルで使える、直前のディレクトリに瞬時に戻る方法を紹介します。

    コマンドラインでのナビゲーションの効率化

    コマンドラインでの作業は速度と効率が重要です。頻繁にディレクトリを行き来する作業は、キーボード入力の手間だけでなく、思考の中断も引き起こします。そこで、直前のディレクトリに素早く戻る方法が必要です。

    cd - コマンド:直前のディレクトリに戻る

    このコマンドは、直前にいたディレクトリに素早く戻るためのコマンドです。これを使用すると、前回までにいたディレクトリに戻ることができます。以下にその使い方を示します。

    この一行のコマンドは、bashや他の多くのシェルでも同様に機能します。

    まとめ

    ターミナルでの作業をより効率的に進めるために、cd - のようなシンプルなコマンドが非常に役立ちます。頻繁にディレクトリを行き来する作業を行っている場合、このコマンドは手間を大幅に削減し、作業の効率を向上させることができます。

     

  • Error response from daemon: Ports are not available: exposing port TCP 127.0.0.1:80 -> 0.0.0.0:0: not allowed as current user. You can enable privileged port mapping from Docker -> Settings… -> Advanced -> Enable privileged port mapping

    Error response from daemon: Ports are not available: exposing port TCP 127.0.0.1:80 -> 0.0.0.0:0: not allowed as current user. You can enable privileged port mapping from Docker -> Settings… -> Advanced -> Enable privileged port mapping

     

     ports:
    - ${LOCAL_IP}:80:80
    - ${LOCAL_IP}:443:443

    docker-compose で上記のように 80, 443 のような 1023 番以下のport をマッピングさせようとしたところ、エラーになることがあります。

    Error response from daemon: Ports are not available: exposing port TCP 127.0.0.1:80 -> 0.0.0.0:0: not allowed as current user.
    You can enable privileged port mapping from Docker -> Settings... -> Advanced -> Enable privileged port mapping

    一般的にエラー文言に従い、Dockerの設定から “Enable privileged port mapping” を有効にしましたが、エラーが解消されない状況に陥りました。

    この問題に直面したとき、Dockerの設定でCLIツールのインストール方法を変更することで回避できました。

    具体的には、Dockerの設定の “Advanced” タブから “Choose how to configure the installation of Docker’s CLI tools” を開き、その設定を “User” から “System” に変更しました。

     

    この変更により、Dockerはシステムレベルで動作するようになり、これにより特権ポートを使用するための必要な権限を得ることができるようになるようです。

    結果として、ポート80と443が正常に割り当てられるようになり、エラーは解消しました。

     

     

  • Warning: Failed to run dot.    Download dot graphvizVersion 2.26 or versions greater than 2.31

    Warning: Failed to run dot. Download dot graphvizVersion 2.26 or versions greater than 2.31

    この警告メッセージは、dot コマンドが利用できないか、または適切なバージョンがインストールされていないことを示しています。dot コマンドは Graphviz パッケージの一部です。

    エラーメッセージ

    状況としては、何らかのアプリケーションまたはスクリプトを実行しているときに次のような警告メッセージが表示されることがあります。

    Warning: Failed to run dot.
    Download dot graphvizVersion 2.26 or versions greater than 2.31
    from www.graphviz.org and make sure that dot is either in your path
    or point to where you installed Graphviz with the -gv option.
    Generated pages will not contain a diagramtic view of table relationships.

    このメッセージは、dot コマンドが利用できないか、または適切なバージョンがインストールされていないことを示しています。

    解決方法

    この問題は、Debian ベースの Linux ディストリビューション(Ubuntu、Debian など)でapt-get を使用して解決することができます。

    1.  リポジトリを更新

    システムのパッケージリストを更新して、最新の情報を取得します。

    sudo apt-get update

    2. Graphviz のインストール

    次に、Graphviz パッケージをインストールします。

    sudo apt-get install graphviz

    4. インストールの確認

    インストールが成功したかどうかを確認するため、dot コマンドのバージョンを確認します。

    dot -V

    これで、バージョン情報が表示されれば、Graphviz は正常にインストールされ、dot コマンドが利用可能な状態になっています。

     

  • PythonでSnowflakeの不要なログを抑制する

    PythonでSnowflakeの不要なログを抑制する

    Snowflake Pythonコネクタは標準のPythonロギングモジュールを使用しています。

    このため、ロギングレベルを変更することで出力されるメッセージの制御が可能です。

    ただし、ロギングレベルを変更することは、接続の状態に関する重要な情報が隠される可能性があります。

    そのため、この変更を行う前に、その意味を完全に理解し、接続が安全であることを確認する必要があります。

    以下に、Snowflakeのロギングレベルを変更する方法を示します。

    1. まず、snowflake.connectorをインポートするPythonモジュールで、コネクタのメソッドを呼び出す前に以下のコードを追加します。これにより、警告またはそれ以上のレベルのログのみが出力されます。
    import logging
    logging.getLogger('snowflake.connector').setLevel(logging.WARNING)
    1. 上記のソリューションでも、すべてのSnowflakeメッセージが消えない場合は、以下のコードを使用して、すべてのSnowflakeロガーをより高いレベルに設定できます。
    import logging
    for name in logging.Logger.manager.loggerDict.keys():
    if 'snowflake' in name:
    logging.getLogger(name).setLevel(logging.WARNING)
    logging.getLogger(name).propagate = False

    この変更により、以下のようなエラーメッセージが表示されなくなります。

    eventType: 'RevocationCheckFailure',
    eventSubType: 'OCSPResponseFailedToConnectCacheServer|OCSPResponseFetchException|OCSPResponseFetchException|OCSPResponseFetchException|OCSPResponseFetchException',
    sfcPeerHost: 'xxxxx.ap-northeast-1.privatelink.snowflakecomputing.com',
    certId: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
    ocspRequestBase64: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
    ocspResponderURL: 'http://o.ss2.us/',
    errorMessage: "254003: Could not fetch OCSP Response from server. Consider checking your whitelists : Exception - HTTPConnectionPool(host='ocsp.xxxxx.ap-northeast-1.privatelink.snowflakecomputing.com', port=80): Max retries exceeded with url: /retry/o.ss2.us/xxxxx+xxx= (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0xffff9c1ec190>: Failed to establish a new connection: [Errno -2] Name or service not known'))",
    insecureMode: False,
    failOpen: True,
    cacheEnabled: True,
    cacheHit: False

    このメッセージは、OCSP(Online Certificate Status Protocol)の検証が失敗した場合に出力されます。OCSPは、TLS接続の設定中に、接続先の証明書が有効であることを確認するためのプロトコルです。このメッセージが表示されるということは、SnowflakeコネクタがOCSP応答を取得できなかったことを示します。このような場合、接続が安全であることを確認した上で、ロギングレベルを変更することを検討してください。

    これらのステップを適用すると、Snowflake Pythonコネクタの不要なログ出力を抑制できます。ただし、これによりエラー情報が失われる可能性があるため、注意が必要です。常に接続が安全であることを確認し、必要に応じて適切なロギングレベルを選択してください。