Dockerを学ぶ5

5日目の具体的なゴール
✅ RailsアプリをDockerで動かす(MySQLと連携)
✅ docker-compose でRailsの開発環境を構築
✅ コンテナ内でのテストの実行を試す

Docker環境でRailsアプリを構築

Railsアプリの作成(my_rails_app ディレクトリを作る)

mkdir my_rails_app
cd my_rails_app

Dockerfile を作成

FROM ruby:3.2
RUN apt-get update -qq && apt-get install -y nodejs postgresql-client
WORKDIR /app
COPY Gemfile Gemfile.lock ./
RUN bundle install
COPY . .
CMD ["rails", "server", "-b", "0.0.0.0"]

Gemfile と Gemfile.lock を用意

Gemfile

source 'https://rubygems.org'
gem 'rails', '~> 7.0'

Gemfile.lock を用意

bundle init
bundle add rails
bundle lock

docker-compose.yml を作成 📄 docker-compose.yml

version: "3.8"

services:
  db:
    image: mysql:5.7
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: myapp_db
      MYSQL_USER: user
      MYSQL_PASSWORD: password
    ports:
      - "3306:3306"
    volumes:
      - db_data:/var/lib/mysql

  web:
    build: .
    ports:
      - "3000:3000"
    depends_on:
      - db
    volumes:
      - .:/app
    environment:
      DATABASE_HOST: db
      DATABASE_USER: user
      DATABASE_PASSWORD: password
      DATABASE_NAME: myapp_db

volumes:
  db_data:

Railsプロジェクトのセットアップ

docker-compose run web rails new . --force --database=mysql

config/database.yml を編集

default: &default
  adapter: mysql2
  encoding: utf8
  pool: 5
  username: <%= ENV['DATABASE_USER'] %>
  password: <%= ENV['DATABASE_PASSWORD'] %>
  host: <%= ENV['DATABASE_HOST'] %>

development:
  <<: *default
  database: <%= ENV['DATABASE_NAME'] %>

データベース作成

docker-compose run web rails db:create

アプリ起動

docker-compose up -d

http://localhost:3000 で確認

  • ChatGPTに出してもらった手順だが、結論としてはこのままだと動かなかった
  • いろいろやったけど何が解決になったのかあんまり考察はできてない
  • まずポイントとしてはrails newを打つとGemfileとDockerfileが上書きされてしまう
    • これは打った後に上書きすることで対応
  • bundle install でなんどもインストールしてもgemが足りないが出続けた
    • やったこと
      • vendor/bundleの永続化
      • その後、docker-compose down --volumeからのdocker-compose build --no-cache
      • Gemfileにたりなかったgemを付け足して、再buildしなおしたりした
source 'https://rubygems.org'
gem 'rails', '~> 7.0'

gem 'bootsnap', require: false
gem 'sprockets-rails'
gem 'mysql2', '~> 0.5'
gem "puma"
  • 色々対応したことでrailsが表示されることは確認できた
  • (後々考えるとホスト上でbundle installできなくて面倒でコンテナ上で試そうとしたので色々違ったことになったのかも)

コンテナ内でテストを実行

RSpecを追加

docker-compose run web bundle add rspec-rails
docker-compose run web rails generate rspec:install
  • ここでもまたinstallしてもありませんが出続けた
  • これも以下で通った
docker-compose down --volumes
docker-compose build --no-cache

テストを実行

docker-compose run web rspec
[+] Creating 1/1
 ✔ Container my_rails_app-db-1  Running                                                                            0.0s
No examples found.


Finished in 0.00032 seconds (files took 0.11349 seconds to load)
0 examples, 0 failures

おわりに

  • ChatGPTは目標を出してくれるのに役立つけど具体的なコマンドやファイルなどは適切なものが出ているのかはあやしい
  • まぁ目標として示されているものにたどり着ければいいので、細かいおかしいとこは自分で解決していくことが勉強にはなるかな

Dockerを学ぶ4

4日目の具体的なゴール
✅ volumes を使ってデータの永続化を試す
✅ .env ファイルを使って環境変数を管理する
✅ docker-compose up の起動順序と depends_on の動作を理解する

volumesを使ってMySQLのデータを永続化

コンテナを起動

docker-compose up -d

MySQLに接続して test_table を作成

CREATE TABLE test_table (id INT PRIMARY KEY, name VARCHAR(50));
INSERT INTO test_table VALUES (1, 'Docker User');
SELECT * FROM test_table;
mysql> SELECT * FROM test_table;
+----+-------------+
| id | name        |
+----+-------------+
|  1 | Docker User |
+----+-------------+
1 row in set (0.00 sec)

MySQLコンテナを停止して再起動し、test_table が消えてしまうことを確認

  • 再アタッチではまだ消えてないが、downからupでは消えていること確認
mysql> SELECT * FROM test_table;
ERROR 1146 (42S02): Table 'testdb.test_table' doesn't exist

docker-compose.yml の db サービスに volumes を追加

services:
  db:
    image: mysql:5.7
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: testdb
      MYSQL_USER: user
      MYSQL_PASSWORD: password
    ports:
      - "3306:3306"
    volumes:
      - db_data:/var/lib/mysql

volumes:
  db_data:
  • 昨日見たvolumesの記憶だとdb_dataという名前付きのvolumeを設定し、コンテナの/var/lib/mysql以下にマウントって感じかな

コンテナを再起動

docker-compose down
docker-compose up -d

MySQLに再接続して test_table のデータが保持されていることを確認

mysql> SELECT * FROM test_table;
+----+-------------+
| id | name        |
+----+-------------+
|  1 | Docker User |
+----+-------------+
1 row in set (0.00 sec)

.envファイルを使って環境変数を管理

.env ファイルを作成し、以下を記述

MYSQL_ROOT_PASSWORD=root
MYSQL_DATABASE=testdb
MYSQL_USER=user
MYSQL_PASSWORD=password

docker-compose.yml を修正し、環境変数を .env から読み込む

services:
  db:
    image: mysql:5.7
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
    ports:
      - "3306:3306"
    volumes:
      - db_data:/var/lib/mysql

コンテナを再起動し、環境変数が適用されているか確認

> docker-compose exec db mysql -uuser -ppassword -D testdb
mysql: [Warning] Using a password on the command line interface can be insecure.
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.44 MySQL Community Server (GPL)

Copyright (c) 2000, 2023, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

depends_on の動作確認

  • depends_on はコンテナの起動順序を制御
  • restart: always では、db が落ちても自動的に再起動
  • healthcheck を組み合わせると、DBが準備完了してから web を起動可能

healthcheck を使ってMySQLの準備完了を待つ

docker-compose.yml に以下を追加

services:
  db:
    image: mysql:5.7
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
    ports:
      - "3306:3306"
    volumes:
      - db_data:/var/lib/mysql
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      retries: 5
  • 再起動して起動順を確認
> docker-compose up -d
[+] Running 3/3
 ✔ Network docker-compose-app_default  Created                                                                     0.3s
 ✔ Container docker-compose-app-db-1   Started                                                                     0.9s
 ✔ Container docker-compose-app-web-1  Started
  • ただ調べた感じだとdepends_onは起動順の制御のみでサービスの稼働までは待ってくれないようなので、気を付ける必要があるらしい

Dockerを学ぶ3

今日のゴールは以下とのことなので進めていきます

✅ docker-compose の基本を理解する
✅ docker-compose.yml を作成し、Webアプリ + DB の環境を構築する
✅ docker-compose up でコンテナを起動・停止できるようになる
✅ docker-compose logs や docker-compose exec でデバッグを試す

docker-compose の基本を学ぶ

docker-compose.yml の主要な構文

Compose ファイル version 2 リファレンス — Docker-docs-ja 24.0 ドキュメント

version

Compose ファイルのバージョンとアップグレード — Docker-docs-ja 24.0 ドキュメント

  • composeのバージョンを指定する

services

  • 起動するコンテナの設定
  • ここ以下の構文で色々設定していく

build

  • build時のコンテキストのパスを指定する
version: "2.4"
services:
  webapp:
    build: ./dir
  • context構文でコンテキストのパスを指定し、さらなるオプションをつけることもできる
  • dockerfileでDockerfileを指定できる
version: "2.4"
services:
  webapp:
    build:
      context: ./dir
      dockerfile: Dockerfile-alternate
      args:
        buildno: 1

ports

  • ポートを公開できる
  • ホスト側:コンテナ側で指定する
ports:
 - "3000"
 - "3000-3005"
 - "8000:8000"
 - "9090-9091:8080-8081"
 - "49100:22"
 - "127.0.0.1:8001:8001"
 - "127.0.0.1:5000-5010:5000-5010"
 - "6060:6060/udp"
 - "12400-12500:1240"

volumes

  • コンテナを消してもデータが残るように永続化する指定ができる
  • [ソース:]ターゲット[:モード] の形式
  • コンテナ上のターゲットで指定された場所が永続化される
  • ソースでホスト側のマウント元を指定できる
  • モードはread-onlyとかread-writeとかの指定らしい
volumes:
  # パスを指定する場合は、Engine がボリュームを作成
  - /var/lib/mysql

  # 絶対パスを指定しての割り当て
  - /opt/data:/var/lib/mysql

  # ホスト上のパスを指定する時は、Compose ファイルからの相対パスを指定
  - ./cache:/tmp/cache

  # ユーザ用ディレクトリのパスを使用
  - ~/configs:/etc/configs/:ro

  # 名前付きボリューム(Named volume)
  • オプションをつけて細かく指定することもできる
    volumes:
      - type: volume
        source: mydata
        target: /data
        volume:
          nocopy: true
      - type: bind
        source: ./static
        target: /opt/app/static

depends_on

  • サービス間の依存関係を示す
  • 以下の場合docker-compose up webでdbとredisも作成起動する
version: "2.4"
services:
  web:
    build: .
    depends_on:
      - db
      - redis
  redis:
    image: redis
  db:
    image: postgres

Webアプリ + MySQLの環境を構築する

  • ChatGPTが作例を出しているので試してみる

app.py(簡単なPython Flaskアプリ)を作成

from flask import Flask
import mysql.connector

app = Flask(__name__)

@app.route('/')
def hello():
    return "Hello, Docker + MySQL!"

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

Dockerfile を作成

FROM python:3.9

WORKDIR /app

COPY requirements.txt .
RUN pip install -r requirements.txt

COPY . .

CMD ["python", "app.py"]

requirements.txt(FlaskとMySQLクライアントをインストール)を作成

flask
mysql-connector-python

docker-compose.yml を作成

version: "3.8"

services:
  web:
    build: .
    ports:
      - "5000:5000"
    depends_on:
      - db

  db:
    image: mysql:5.7
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: testdb
      MYSQL_USER: user
      MYSQL_PASSWORD: password
    ports:
      - "3306:3306"

docker-compose を使って環境を立ち上げる

コンテナを起動

docker-compose up -d

動作確認(ブラウザで http://localhost:5000 を開く)

コンテナのログを見る

> docker-compose logs web
time="2025-03-22T16:19:25+09:00" level=warning msg="C:\\Users\\mir3636\\docker-compose-app\\docker-compose.yml: the attribute `version` is obsolete, it will be ignored, please remove it to avoid potential confusion"
web-1  |  * Serving Flask app 'app'
web-1  |  * Debug mode: off
web-1  | WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
web-1  |  * Running on all addresses (0.0.0.0)
web-1  |  * Running on http://127.0.0.1:5000
web-1  |  * Running on http://172.18.0.3:5000
web-1  | Press CTRL+C to quit
web-1  | 172.18.0.1 - - [22/Mar/2025 07:17:21] "GET / HTTP/1.1" 200 -
web-1  | 172.18.0.1 - - [22/Mar/2025 07:17:21] "GET /favicon.ico HTTP/1.1" 404 -

version いらないらしい(笑)

コンテナの中に入る(デバッグ

docker-compose exec web sh
# ls
Dockerfile  app.py  docker-compose.yml  requirements.txt
# ls ../
app  bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
  • コンテナ内に入れたのでlsとか叩いてみた
  • Dockerfileで指定した通りワーキングディレクトリはappになっている
  • COPYで作業ディレクトリ内のファイルをコピーしているので存在している
> docker-compose exec db mysql -uuser -ppassword -D testdb
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.44 MySQL Community Server (GPL)

Copyright (c) 2000, 2023, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
  • DB側も確認できた
  • ホストのPCではMySQLの環境なんて作ってないのに動いていてすごい

docker-compose down

  • 片付けコマンド
  • localhost見ても落ちていること確認

おわりに

  • 目を通したかったことは全部通したなという感じがする
  • あとは細かいとこ調べつつなら開発環境のDocker化してみることができそう
  • ChatGPTすごい。指針を示してくれるのはなんもわからんから始めるときのハードルがかなり低くなるね

Dockerを学ぶ2

学習2日目の目標をChatGPTに出してもらってスタート

Docker学習2日目の目標は、Dockerfileを使って独自のDockerイメージを作成し、コンテナを実行することです。

2日目の具体的なゴール
✅ Dockerfile の基本構文を理解する
✅ シンプルなアプリのDockerイメージを作成する
✅ docker build でイメージを作成し、コンテナを実行する
✅ docker-compose の概要を知る
以下略

Dockerfileの基本を学ぶ

docs.docker.jp

  • Dockerfile から命令を読み込み、イメージをビルドできる
  • docker build コマンドでDockerfileと指定したパスの環境からイメージをビルドする

Dockerfile の構文

命令 引数の形式で記述される

FROM

FROM [--platform=<プラットフォーム>] <イメージ名>[:<タグ>] [AS <名前>]
  • FROM命令で構築のベースとなるイメージを指定できる
  • Dockerfile は必ず FROM 命令で始めることになるらしい
  • 例外としてARG命令があるが、これはFROM命令の引数として扱う命令
    • FROM命令より前に宣言されたARG命令は構築ステージ外なのでFROM命令以降では使えない

COPY

COPY [--chown=<ユーザ>:<グループ>] <コピー元>... <コピー先>
COPY [--chown=<ユーザ>:<グループ>] ["<コピー元>",... "<コピー先>"]
  • COPY命令は指定したファイルをイメージのファイルシステム上にコピーすることができる
  • COPY元のファイルやディレクトリはdocker buildしたコンテキスト内にある必要がある

RUN

RUN <コマンド>
  • シェル形式のコマンドを実行できる

CMD

CMD ["実行ファイル","パラメータ1","パラメータ2"]
CMD ["パラメータ1", "パラメータ2"] 
CMD コマンド パラメータ1 パラメータ2 #シェル形式
  • CMD 命令は Dockerfile 中で1度しか使えない
  • CMD の主な目的は、コンテナ実行時のデフォルト(初期設定)を指定するため
  • CMDはRUNと違い、構築時には何も実行せず、コンテナ起動時に実行される

EXPOSE

EXPOSE <ポート> [<ポート>/<プロトコル>...]
  • コンテナの指定したポートを公開する
  • 命令を記述しただけでは実際には公開せず、docker run時に-pオプションをつけることで公開される

簡単なDockerfileを作成する

ChatGPT君が作成例を出してくれているのでそのまま使用してみる 1. Dockerfileを作成

# Pythonの公式イメージを使用
FROM python:3.9

# 作業ディレクトリを作成
WORKDIR /app

# スクリプトをコンテナ内にコピー
COPY app.py .

# コンテナ起動時に実行するコマンド
CMD ["python", "app.py"]
  1. app.py を作成
print("Hello, Docker!")
  1. Dockerイメージをビルド & 実行
docker build -t my-python-app .
docker run my-python-app
> docker run my-python-app
Hello, Docker!

できた

docker-composeの概要を学ぶ

docs.docker.jp

  • Composeとは複数のコンテナを定義し、実行するツール(WEBアプリ+DBのコンテナを一括管理できる)
  • コマンドを1つ実行するだけで、設定内容に基づいた全てのサービスを生成・起動する
  • docker-compose.yml で記述し、docker compose upで実行できる
  • docker-compose.ymlの例
version: "3.9"  # v1.27.0 からはオプション
services:
  web:
    build: .
    ports:
      - "8000:5000"
    volumes:
      - .:/code
      - logvolume01:/var/log
    links:
      - redis
  redis:
    image: redis
volumes:
  logvolume01: {}

Dockerを学ぶ

勉強のクセを取り戻すためにリハビリをしてみようと思ったので久しぶりに更新

3日坊主かもしれないけどやらないよりはマシか

はじめに

Docker を学ぶとはいえ何から手を付けていけば・・・

ということでChatGPTに出してもらった

Q: Dockerの学習を進めたい1日目の目標は?
A: Docker学習1日目の目標は、Dockerの基本概念を理解し、簡単なコンテナを実行できるようになることです。

1日目の具体的なゴール
✅ Dockerとは何かをざっくり理解する
✅ Dockerをインストールする
✅ 基本的なコマンドを試してみる
✅ シンプルなコンテナを動かしてみる

以下略 

便利な世の中になったな・・・

Dockerの基本を理解する

ChatGPTの言う通り学んでいこうと思う

まずはDockerの基本を理解するということで Dockerとは docs.docker.com

  • Dockerとはコンテナと呼ばれる分離された環境でアプリケーションの実行することができるプラットフォームである
  • コンテナはホストとは分離された環境のため、ホストの環境に依存しない
  • 複数のコンテナを同時実行できる
  • コンテナは共有可能で共有することで他の人も同じ様に動作する環境を得られる(CI/CDにつかえる)

Dockerを取り巻くワード

イメージ

コンテナ

  • イメージからインスタンス化された仮想環境
  • Docker API または CLI を使用して、コンテナを作成、開始、停止、移動、または削除できる
  • コンテナが削除されると、永続ストレージに保存されていない状態の変更はすべて消える
  • VMとは違い、カーネルはホストを共有するので軽量
  • MacとかWindowsでどうやってLinuxの環境使ってるの?と思ったらVM上にコンテナを立てているらしい

Dockerをインストールする

https://www.docker.com/ja-jp/

  • 遊ぶことしか考えてなくてWindows買ったのでWindowsからやってみる
  • 始めようと思ったらLinuxWindows サブシステムを更新しろと言われて終了したので指示に従って更新
  • アカウント登録して完了
> docker --version
Docker version 27.5.1, build 9f9e405

Windows PowerShellはじめてつかったので感動

基本的なコマンドを試してみる

docker run

  • hello-world用のイメージがあるらしい
> docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
e6590344b1a5: Download complete
Digest: sha256:7e1a4e2d11e2ac7a8c3f768d4166c2defeb09d2a750b010412b6ea13de1efb19
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/
  • local に存在しなかったのでhello-worldイメージをpullして実行しているっぽい

docker images

  • 持っているイメージを確認できる
> docker images
REPOSITORY    TAG       IMAGE ID       CREATED       SIZE
hello-world   latest    7e1a4e2d11e2   8 weeks ago   20.4kB

docker pull

  • 公式のイメージをpullできる
> docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
c22eb46e871a: Download complete
417c4bccf534: Download complete
97f5c0f51d43: Download complete
373fe654e984: Download complete
6e909acdb790: Download complete
5eaa34f5b9c2: Download complete
e7e0ca015e55: Download complete
Digest: sha256:124b44bfc9ccd1f3cedf4b592d4d1e8bddb78b51ec2ed5056c52d3692baebc19
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest
  • 特に指定なければ最新版をとってきているみたい
> docker images
REPOSITORY    TAG       IMAGE ID       CREATED       SIZE
nginx         latest    124b44bfc9cc   5 weeks ago   279MB
hello-world   latest    7e1a4e2d11e2   8 weeks ago   20.4kB
  • 増えていること確認
> docker run -d -p 8080:80 nginx
dccff607e1048c507747681105b39947334315fc6db4bb7999154c866d8312a3
  • 実行してみた
  • -dはアタッチせずに実行らしい。-pはポートだろう
  • docker attach でアタッチできるらしい。hash指定

  • ブラウザで見てみる

  • 起動している

docker ps

  • 起動中のコンテナを確認できる
> docker ps
CONTAINER ID   IMAGE     COMMAND                   CREATED         STATUS         PORTS                  NAMES
dccff607e104   nginx     "/docker-entrypoint.…"   5 minutes ago   Up 5 minutes   0.0.0.0:8080->80/tcp   tender_hamilton

docker stop

  • 停止コマンド。psで停止していることがわかる
> docker stop dccff607e104
dccff607e104
> docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

おわりに

Dockerが何なのか、基本的なコマンドがなんとなくわかった

必要にせまられて軽く触ったことはあったのでまぁリハビリにはちょうどいい感じだった

これやると遊ぶ時間なくなるなぁ平日はもう少し短い時間でやってもいいかも

Ruby 3.1 を install した

Ruby で何かやろうと思ったけどせっかくなので新しい方をinstallしてみた

色々引っかかったのでもうこれ記事でいいなって思ったので書いた

1年ぶりくらいの brew upgrade rbenv

  • 結構時間かかった
  • 色々アップデートされてたけどウインドウ閉じちゃって見返せないので割愛

rbenv install --list 打ってみる

> rbenv install --list
2.6.10
2.7.6
3.0.4
3.1.2
jruby-9.3.9.0
mruby-3.1.0
picoruby-3.0.0
rbx-5.0
truffleruby-22.3.0
truffleruby+graalvm-22.3.0

Only latest stable releases for each Ruby implementation are shown.
Use 'rbenv install --list-all / -L' to show all local versions.

3.1系の最新は3.1.2なので落としてみる

rbenv install 3.1.2

Installing ruby-3.1.2...
ruby-build: using readline from homebrew
ruby-build: using gmp from homebrew

BUILD FAILED (macOS 11.6.8 using ruby-build 20221101)

Last 10 log lines:
compiling dln.c
compiling localeinit.c
In file included from yjit.c:158:
./yjit_iface.c:17:10: fatal error: 'capstone/capstone.h' file not found
#include <capstone/capstone.h>
         ^~~~~~~~~~~~~~~~~~~~~
compiling array.c
1 error generated.
make: *** [Makefile:434: yjit.o] Error 1
make: *** Waiting for unfinished jobs....

早速のError

まぁ久しぶりだしね・・・

./yjit_iface.c:17:10: fatal error: 'capstone/capstone.h' file not found

エラーの原因はcapstoneとやらが無いからのようで・・・

yjit_iface.cこれが噂のYJITか・・・!

capstoneはディスアセンブラフレームワークらしい

YJITはこれを使ってるってことなのか

www.capstone-engine.org

brew install capstoneを打ってみるが既に入っている

ググってみると以下を発見

github.com

あ、なるほど、CFLAGSとLDFLAGS渡してあげればいいのか

/usr/local/Cellar以下に入っていたので

$ export CFLAGS="-I/usr/local/Cellar/capstone/4.0.2/include"
$ export LDFLAGS="-L/usr/local/Cellar/capstone/4.0.2/lib"

これで通ってそう...と思ったらまた新たなエラーを踏む

/private/var/folders/6j/q4gjr83j1kn6y1gszxjwdzdh0000gn/T/ruby-build.20221115235314.327.LDBVvA/ruby-3.1.2/lib/fileutils.rb:240:in `mkdir': Permission denied @ dir_s_mkdir - /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.1.sdk/Users (Errno::EACCES)
    from /private/var/folders/6j/q4gjr83j1kn6y1gszxjwdzdh0000gn/T/ruby-build.20221115235314.327.LDBVvA/ruby-3.1.2/lib/fileutils.rb:240:in `fu_mkdir'
    from /private/var/folders/6j/q4gjr83j1kn6y1gszxjwdzdh0000gn/T/ruby-build.20221115235314.327.LDBVvA/ruby-3.1.2/lib/fileutils.rb:221:in `block (2 levels) in mkdir_p'
    from /private/var/folders/6j/q4gjr83j1kn6y1gszxjwdzdh0000gn/T/ruby-build.20221115235314.327.LDBVvA/ruby-3.1.2/lib/fileutils.rb:219:in `reverse_each'
    from /private/var/folders/6j/q4gjr83j1kn6y1gszxjwdzdh0000gn/T/ruby-build.20221115235314.327.LDBVvA/ruby-3.1.2/lib/fileutils.rb:219:in `block in mkdir_p'
    from /private/var/folders/6j/q4gjr83j1kn6y1gszxjwdzdh0000gn/T/ruby-build.20221115235314.327.LDBVvA/ruby-3.1.2/lib/fileutils.rb:211:in `each'
    from /private/var/folders/6j/q4gjr83j1kn6y1gszxjwdzdh0000gn/T/ruby-build.20221115235314.327.LDBVvA/ruby-3.1.2/lib/fileutils.rb:211:in `mkdir_p'
    from ./tool/rbinstall.rb:218:in `makedirs'
    from ./tool/rbinstall.rb:331:in `prepare'
    from ./tool/rbinstall.rb:432:in `block in <main>'
    from ./tool/rbinstall.rb:1127:in `block in <main>'
    from ./tool/rbinstall.rb:1124:in `each'
    from ./tool/rbinstall.rb:1124:in `<main>'
make: *** [uncommon.mk:383: do-install-all] Error 1

Permission denied !?何故?全然わからん

ググってみると同じような状態の人が見つかる

github.com

@BytesGuy Do you have this line export SDKROOT=$(xcrun -sdk macosx --show-sdk-path) in .barhrc or .zshrc?

For me, after i comment this line out, it works fine.

ドンピシャでこれだった

.zshrcexport SDKROOT="$(xcrun --sdk macosx --show-sdk-path)"コメントアウトすることで解決

これって何で入れたやつだっけ?

これからは.zshrcに何か書き足すときはコメント入れることにしよう・・・

無事インストール完了

FaradayでSlackにファイルアップロードする

リハビリ記事

目的

SlackにCSVファイルを投げつけたかった

はじめに

以下を参考にSlack Appを作成し、Tokenを取得 qiita.com

files.uploadを読んでみる api.slack.com とりあえずCSVファイルが投げれれば良かったのでsystemで書いてみる

  system("curl -F file=@#{file_path} -F channels=#{channel_id} -F token=#{token} -F initial_comment=#{comment}  https://slack.com/api/files.upload")

書いてみたものの他でも使うかもしれないのでもうちょっとちゃんと書くことにする

Faraday使った実装

lostisland.github.io 不真面目なのでとりあえず楽そうに書いてみる

require "faraday"

class SlackFileUploadService
  def self.file_upload(file_path:, channel_id:, comment:)
    faraday = Faraday.new(url: "https://slack.com")

    token = Token # 取得したtoken
    
    faraday.post("api/files.upload", file: file_parh, channels: channel_id, token: token, initial_comment: comment)
  end
end

SlackFileUploadService.file_upload(file: file_path, channel_id: channel_id, comment: comment)

エラーが返ってきた

{"ok":false,"error":"no_file_data"}

どうやらFilePath投げるだけじゃダメらしい

ファイルの送信方法でググってみる

こちらを見るとFaraday::UploadIO使わないといけないらしい crieit.net

再度チャレンジ

今度はfileで一度Faraday::UploadIOで受けてから実行

require "faraday"

class SlackFileUploadService
  def self.file_upload(file_path:, channel_id:, comment:)
    faraday = Faraday.new(url: "https://slack.com")

    token = Token
    file = Faraday::UploadIO.new(file_path, "text/plain")
    
    faraday.post("api/files.upload", file: file, channels: channel_id, token: token, initial_comment: comment)
  end
end

SlackFileUploadService.file_upload(file: file_path, channel_id: channel_id, comment: comment)

変わらずエラー

{"ok":false,"error":"no_file_data"}

そもそもcurl-Fってなんだと思い調べてみる www.y-hakopro.com

-Fオプション使用時のContent-Typeはデフォルトで「multipart/form-data」が指定される。

ここでmultipart/form-dataというワードを入手した

multipartというワードを入手した状態で改めてfile uploadをググっていると stackoverflow.com どうやらFaraday.newの際に色々指定しなければいけないらしい

指定している内容はググると詳しそうなページが当たった

(たくさんタメになりそうな事書かれていそうなので後で全部読んでおきたい) nekorails.hatenablog.com

再再チャレンジ

require "faraday"

class SlackFileUploadService
  def self.file_upload(file_path:, channel_id:, comment:)
    faraday = Faraday.new(url: "https://slack.com") do |f|
      f.request :multipart
      f.request :url_encoded
      f.adapter Faraday.default_adapter
    end

    token = Token
    file = Faraday::UploadIO.new(file_path, "text/plain")
    
    faraday.post("api/files.upload", file: file, channels: channel_id, token: token, initial_comment: comment)
  end
end

SlackFileUploadService.file_upload(file: file_path, channel_id: channel_id, comment: comment)

成功!

{"ok":true,"file":以下略}

無事SlackにもCSVが投下されました

めでたし