20210727のdockerに関する記事は9件です。

RaspberryPiでamd64のDockerイメージを起動する(夢を見た)

注意 この記事ではRaspberryPi上のDockerでarmではないamd64のDockerイメージを起動するという通常は使わないとてもニッチなことを紹介しています。 amd64でRaspberryPiOSを起動したり、armのイメージを実行したりするわけではないのでご注意ください。 なんとなくの思いつきで試してみたらできてしまった(できそうになってしまった)アイディアをまとめました。ただし、動作が不安定(多くのアプリケーションでsegmentation faultが起きる)で実用性はおそらくないので「へー」ぐらいで読んでいただければ幸いです。笑 TL;DR # 通常通りDockerをインストールする curl -sSL https://get.docker.com | sh # rootでdockerを使うのが面倒なのでpiをdockerグループに追加する sudo usermod -aG docker pi # amd64イメージを実行するためにQEMUをインストールする sudo apt install qemu-user-static ちょっとだけ解説 dockerのplatform属性 AppleSilicon対応の影響を受けてか、dockerにplatformオプションが追加されました。 例えばarm環境でamd64のイメージを起動するときは下記のようなコマンドになります。 docker run -it --platform=linux/amd64 ubuntu しかし当然、通常ではarmでamd64のバイナリを実行することができないため、下のようにexec formatエラーが出てきます。 pi@raspberrypi:~ $ docker run -it --platform=linux/amd64 ubuntu Unable to find image 'ubuntu:latest' locally latest: Pulling from library/ubuntu 16ec32c2132b: Pull complete Digest: sha256:82becede498899ec668628e7cb0ad87b6e1c371cb8a1e597d83a47fac21d6af3 Status: Downloaded newer image for ubuntu:latest standard_init_linux.go:228: exec user process caused: exec format error pi@raspberrypi:~ $ しかしもしこの時にQEMUのように違うアーキテクチャをエミュレーションするようなアプリケーションを挟むことができたら…ということで今回はやっていきます。 QEMU QEMUは広く使われているオープンソースのマシンエミュレータと仮想化アプリケーションです。 簡単に言えば仮想マシンを起動するためのアプリケーションです。 今回はOSごとではなくアプリケーションを実行するだけなのでユーザモードエミュレーション用のqemu-user-staticを使います。 binfmt_misc 今回のキモと言ってもいいかもしれません。 binfmt_miscはあらゆるファイルを実行できるようにファイルの構造を認識し、適切なアプリケーションで実行させるためのLinuxの仕組みの1つです。Linux上でWindowsのアプリケーションを実行できるようにするアプリケーションWineでも使用されているようです。 この仕組みを利用し、x86、amd64などのバイナリの実行を検知したらqemuに通すようにします。 この辺りについてはqemu-user-staticをインストールするときに一緒にインストールされるbinfmt-supportがいい感じに設定してくれます。 実行結果 pi@raspberrypi:~ $ docker run -it --platform=linux/amd64 ubuntu root@2717779fa63a:/# uname -a Linux 2717779fa63a 5.10.17-v7l+ #1414 SMP Fri Apr 30 13:20:47 BST 2021 x86_64 x86_64 x86_64 GNU/Linux root@2717779fa63a:/# ls bin dev home lib32 libx32 mnt proc run srv tmp var boot etc lib lib64 media opt root sbin sys usr root@2717779fa63a:/# cat /etc/os-release NAME="Ubuntu" VERSION="20.04.2 LTS (Focal Fossa)" ID=ubuntu ID_LIKE=debian PRETTY_NAME="Ubuntu 20.04.2 LTS" VERSION_ID="20.04" HOME_URL="https://www.ubuntu.com/" SUPPORT_URL="https://help.ubuntu.com/" BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/" PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy" VERSION_CODENAME=focal UBUNTU_CODENAME=focal root@2717779fa63a:/# unameの実行結果からもわかるように無事にamd64のUbuntuイメージの実行に成功しました! …がこれには続きがあり、 (都合上上記とは違う、バージョンの古いイメージを使用しています。) root@131b5d842de4:/# apt upgrade Reading package lists... Done Building dependency tree Reading state information... Done Calculating upgrade... Done The following packages will be upgraded: apt base-files bsdutils fdisk gcc-8-base gpgv gzip libapt-pkg5.0 libaudit-common libaudit1 libblkid1 libc-bin libc6 libfdisk1 libgcc1 libgnutls30 libhogweed4 liblz4-1 libmount1 libnettle6 libp11-kit0 libpam-modules libpam-modules-bin libpam-runtime libpam0g libseccomp2 libsmartcols1 libstdc++6 libsystemd0 libudev1 libuuid1 libzstd1 mount perl-base tar ubuntu-keyring util-linux 37 upgraded, 0 newly installed, 0 to remove and 0 not upgraded. Need to get 11.8 MB of archives. After this operation, 114 kB of additional disk space will be used. Do you want to continue? [Y/n] Get:1 http://archive.ubuntu.com/ubuntu bionic-updates/main i386 gcc-8-base i386 8.4.0-1ubuntu1~18.04 [18.7 kB] Get:2 http://archive.ubuntu.com/ubuntu bionic-updates/main i386 libgcc1 i386 1:8.4.0-1ubuntu1~18.04 [48.3 kB] Get:3 http://archive.ubuntu.com/ubuntu bionic-updates/main i386 libstdc++6 i386 8.4.0-1ubuntu1~18.04 [432 kB] ...省略... Unpacking util-linux (2.31.1-0.4ubuntu3.7) over (2.31.1-0.4ubuntu3.5) ... Setting up util-linux (2.31.1-0.4ubuntu3.7) ... (Reading database ... 4040 files and directories currently installed.) Preparing to unpack .../libc-bin_2.27-3ubuntu1.4_i386.deb ... Unpacking libc-bin (2.27-3ubuntu1.4) over (2.27-3ubuntu1) ... Setting up libc-bin (2.27-3ubuntu1.4) ... Segmentation fault (core dumped) Segmentation fault (core dumped) dpkg: error processing package libc-bin (--configure): installed libc-bin package post-installation script subprocess returned error exit status 139 Errors were encountered while processing: libc-bin E: Sub-process /usr/bin/dpkg returned an error code (1) root@131b5d842de4:/# と言ったようにSegmentation faultで正常にアプリケーションが実行できないこともあります。 (armのカーネルでamd64を動かすという無理をしているせいかもしれません… もしこの辺り詳しい人がいらっしゃいましたらコメントいただけると嬉しいです。) あまり安定していないので実用的ではないかなというのが個人的な感想です。 あとがき もともとこの内容はRaspberryPiのカーネルをamd64の環境でビルドする際にbinfmt_miscとqemuを使うという手法を用いることを知ったのがきっかけでした。 まさかRaspberryPiでamd64のdockerイメージを実行するというところに応用できるとは思っていませんでした。 こうしてまた役に立たなそうな謎の知見を得られましたが、誰かのためになったらいいなと頭の片隅で願っています。 誤字、脱字、間違い等がありましたらご指摘いただければ幸いです。 Reference https://docs.docker.com/docker-for-mac/apple-silicon/ https://qiita.com/HyunwookPark/items/6e4854248c6d63958060 https://papamitra.hatenadiary.org/entry/20071215/binfmt https://en.wikipedia.org/wiki/Binfmt_misc https://www.qemu.org
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Docker起動時に Fatal Error Failed to ping backend API という警告が出た場合の対処法

macでDocker起動時に Fatal Error Failed to ping backend API という警告のウィンドウが出た場合の対処法です。 Reset Docker to factory defaults Diagnose & Feedback Exit この3つの選択肢がありますが、どれを押しても反応しない現象が発生しています。 環境 macOS Big Sur 11.3.1 Docker Desktop 3.5.2 対処法 $ killall Docker && cd /Applications;open -a Docker;cd ~ まずDockerのプロセスを強制終了させます。 そしてApplicationsフォルダから改めてDockerを起動します。 こちらのissueで詳しく議論されています。 こちら頻繁に発生する現象ですので、このissue内でも紹介されているように .zshrc 等に以下の記述を追加して、コマンドをエイリアスとして登録すると良さそうです。 alias rdocker="killall Docker && cd /Applications;open -a Docker;cd ~"
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

.NET 6 Preview 6をDocker上で動かしてみました。

はじめに Dockerの勉強として、先日リリースされた.NET 6 Preview 6をDocker上で動かしてみました。 Preview版のSDKをローカルにインストールするのは悩むなぁという方は参考になるかもしれません。 以下の記事がとても参考になりました。ありがとうございます!! https://qiita.com/karuakun/items/054701beed6cd925d7d2 Dockerコンテナ内でMVCプロジェクトを立てる! .NET 6 Preview 6のイメージを以下から取得し、コンテナを立ち上げます。 https://hub.docker.com/_/microsoft-dotnet-nightly-sdk/ ※今回はUbuntu環境のイメージを利用しました。 C:\Work\Docker_.Net6Preview>docker run -it -p 5000:5000 -v c:\Work\Docker_.Net6Preview:/src mcr.microsoft.com/dotnet/sdk:6.0-focal ※ポートは5000、ローカル環境のc:\Work\Docker_.Net6Previewフォルダをコンテナ内のsrcフォルダへマウントしています。 コンテナを立ち上げた後はsrcフォルダ内で以下のようにMVCプロジェクトを立ち上げてみます。 root@a5d31eefeda7:/# cd src root@a5d31eefeda7:/src# ls root@a5d31eefeda7:/src# mkdir WebSite1 root@a5d31eefeda7:/src# cd WebSite1/ root@a5d31eefeda7:/src/WebSite1# dotnet new mvc The template "ASP.NET Core Web App (Model-View-Controller)" was created successfully. This template contains technologies from parties other than Microsoft, see https://aka.ms/aspnetcore/6.0-third-party-notices for details. Processing post-creation actions... Running 'dotnet restore' on /src/WebSite1/WebSite1.csproj... Determining projects to restore... Restored /src/WebSite1/WebSite1.csproj (in 69 ms). Restore succeeded. Restore succeededと出たので問題なく出来上がったようです。 dotnet runコマンドでMVCプロジェクトを実行してみましょう。 --urlsでURLとポートの形式を指定します。 root@a5d31eefeda7:/src/WebSite1# dotnet run --urls http://*:5000 Building... warn: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[60] Storing keys in a directory '/root/.aspnet/DataProtection-Keys' that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed. info: Microsoft.Hosting.Lifetime[14] Now listening on: http://[::]:5000 info: Microsoft.Hosting.Lifetime[0] Application started. Press Ctrl+C to shut down. info: Microsoft.Hosting.Lifetime[0] Hosting environment: Development info: Microsoft.Hosting.Lifetime[0] Content root path: /src/WebSite1 warn: Microsoft.AspNetCore.HttpsPolicy.HttpsRedirectionMiddleware[3] Failed to determine the https port for redirect. localhost:5000へアクセスしてみると・・・ お!しっかり表示されていますね!(^^)! 良い感じです。 コンテナを立ち上げる際にローカルフォルダへマウントしていますので、対象のフォルダからタイトルを変えてみましょう。 タイトルを「Welcome」→「Welcome変更しました」としてみました。 しっかり変わっていますね! .NET 6 Preview 6で追加されたコマンドも試してみる 以下の記事で.NET 6 Preview 6にて追加されたコマンドがあるようですのでその中の1つである「dotnet workload search」というコマンドを打ってみました。 https://devblogs.microsoft.com/dotnet/announcing-net-6-preview-6/ インストール可能なワークロードがいくつか出ていることが分かります。 root@a5d31eefeda7:/src/WebSite1# dotnet workload search Workload ID Description ----------------------------------------------------------------------------------------- microsoft-net-sdk-blazorwebassembly-aot Browser Runtime native performance tools microsoft-net-runtime-android Android Mono Runtime microsoft-net-runtime-android-aot Android Mono AOT Workload microsoft-net-runtime-ios iOS Mono Runtime and AOT Workload microsoft-net-runtime-maccatalyst MacCatalyst Mono Runtime and AOT Workload microsoft-net-runtime-tvos tvOS Mono Runtime and AOT Workload microsoft-net-runtime-mono-tooling Shared native build tooling for Mono runtime microsoft-android-sdk-full Android SDK microsoft-maccatalyst-sdk-full Microsoft MacCatalyst SDK maui .NET MAUI SDK for all platforms maui-mobile .NET MAUI SDK for Mobile maui-desktop .NET MAUI SDK for Desktop maui-core .NET MAUI SDK Core Packages maui-android .NET MAUI SDK for Android maui-maccatalyst .NET MAUI SDK for Mac Catalyst maui-ios .NET MAUI SDK for iOS maui-windows .NET MAUI SDK for Windows microsoft-macos-sdk-full Microsoft macOS SDK microsoft-ios-sdk-full Microsoft iOS SDK microsoft-tvos-sdk-full Microsoft tvOS SDK おわりに Dockerはこんな感じで簡単に環境が作れてしまうのでとても良いですね!(イメージが用意されてればではありますが・・・) 今まではローカルの方にインストールしまくっていたので今後は積極的に利用していかねば!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

.NET 6 PreviewをDocker上で動かしてみました。

はじめに Dockerの勉強として、.NET 6 PreviewをDocker上で動かしてみました。 Preview版のSDKをローカルにインストールするのは悩むなぁという方は参考になるかもしれません。 以下の記事がとても参考になりました。ありがとうございます!! Dockerコンテナ内でMVCプロジェクトを立てる! .NET 6 Previewのイメージを以下から取得し、コンテナを立ち上げます。 https://hub.docker.com/_/microsoft-dotnet-nightly-sdk/ ※今回はUbuntu環境のイメージを利用しました。 C:\Work\Docker_.Net6Preview>docker run -it -p 5000:5000 -v c:\Work\Docker_.Net6Preview:/src mcr.microsoft.com/dotnet/sdk:6.0-focal ※ポートは5000、ローカル環境のc:\Work\Docker_.Net6Previewフォルダをコンテナ内のsrcフォルダへマウントしています。 コンテナを立ち上げた後はsrcフォルダ内で以下のようにMVCプロジェクトを立ち上げてみます。 root@a5d31eefeda7:/# cd src root@a5d31eefeda7:/src# ls root@a5d31eefeda7:/src# mkdir WebSite1 root@a5d31eefeda7:/src# cd WebSite1/ root@a5d31eefeda7:/src/WebSite1# dotnet new mvc The template "ASP.NET Core Web App (Model-View-Controller)" was created successfully. This template contains technologies from parties other than Microsoft, see https://aka.ms/aspnetcore/6.0-third-party-notices for details. Processing post-creation actions... Running 'dotnet restore' on /src/WebSite1/WebSite1.csproj... Determining projects to restore... Restored /src/WebSite1/WebSite1.csproj (in 69 ms). Restore succeeded. Restore succeededと出たので問題なく出来上がったようです。 dotnet runコマンドでMVCプロジェクトを実行してみましょう。 --urlsでURLとポートの形式を指定します。 root@a5d31eefeda7:/src/WebSite1# dotnet run --urls http://*:5000 Building... warn: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[60] Storing keys in a directory '/root/.aspnet/DataProtection-Keys' that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed. info: Microsoft.Hosting.Lifetime[14] Now listening on: http://[::]:5000 info: Microsoft.Hosting.Lifetime[0] Application started. Press Ctrl+C to shut down. info: Microsoft.Hosting.Lifetime[0] Hosting environment: Development info: Microsoft.Hosting.Lifetime[0] Content root path: /src/WebSite1 warn: Microsoft.AspNetCore.HttpsPolicy.HttpsRedirectionMiddleware[3] Failed to determine the https port for redirect. localhost:5000へアクセスしてみると・・・ お!しっかり表示されていますね!(^^)! 良い感じです。 コンテナを立ち上げる際にローカルフォルダへマウントしていますので、対象のフォルダからタイトルを変えてみましょう。 タイトルを「Welcome」→「Welcome変更しました」としてみました。 しっかり変わっていますね! .NET 6 Preview 6で追加されたコマンドも試してみる 現時点(この記事を書いた2021年7月27日)で最新のバージョンとなっている.NET 6 Preview 6について、以下の記事で追加されたコマンドがあるようですのでその中の1つである「dotnet workload search」というコマンドを打ってみました。 dotnet workload searchコマンドはインストール可能なワークロードを表示します。 以下のようにインストール可能なワークロードがいくつか出ていることが分かります。 (どうやらPreview6にも対応してるっぽいですね。) root@a5d31eefeda7:/src/WebSite1# dotnet workload search Workload ID Description ----------------------------------------------------------------------------------------- microsoft-net-sdk-blazorwebassembly-aot Browser Runtime native performance tools microsoft-net-runtime-android Android Mono Runtime microsoft-net-runtime-android-aot Android Mono AOT Workload microsoft-net-runtime-ios iOS Mono Runtime and AOT Workload microsoft-net-runtime-maccatalyst MacCatalyst Mono Runtime and AOT Workload microsoft-net-runtime-tvos tvOS Mono Runtime and AOT Workload microsoft-net-runtime-mono-tooling Shared native build tooling for Mono runtime microsoft-android-sdk-full Android SDK microsoft-maccatalyst-sdk-full Microsoft MacCatalyst SDK maui .NET MAUI SDK for all platforms maui-mobile .NET MAUI SDK for Mobile maui-desktop .NET MAUI SDK for Desktop maui-core .NET MAUI SDK Core Packages maui-android .NET MAUI SDK for Android maui-maccatalyst .NET MAUI SDK for Mac Catalyst maui-ios .NET MAUI SDK for iOS maui-windows .NET MAUI SDK for Windows microsoft-macos-sdk-full Microsoft macOS SDK microsoft-ios-sdk-full Microsoft iOS SDK microsoft-tvos-sdk-full Microsoft tvOS SDK おわりに Dockerはこんな感じで簡単に環境が作れてしまうのでとても良いですね!(イメージが用意されてればではありますが・・・) 今まではローカルの方にインストールしまくっていたので今後は積極的に利用していかねば!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

FastAPIの認証付き開発環境を整える

TL;DR コードはここに一式置いてあります。 https://github.com/inunekousapon/easy_fastapi 環境 MacOS Big Sur バージョン11.4 Docker Desktop Version 3.4.0 作るもの FastAPIが動くこと MySQLと繋がっていること 認証の仕組みが整っていること JWTで認証と認可ができること FastAPIのDockerを作る Github公式 https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker FROM tiangolo/uvicorn-gunicorn-fastapi:python3.8 COPY ./app/requirements.txt /app RUN pip install -r requirements.txt ライブラリをインストールするためにappディレクトリを作成し、requirements.txtを追加します。 . ├── Dockerfile ├── app │ └── requirements.txt requirements.txtにはJWTの認証に必要なライブラリとデータベースの接続に必要なものを指定しておきます。 requirements.txt python-jose[cryptography]== 3.3.0 passlib[bcrypt]==1.7.4 SQLAlchemy==1.4.22 pymysql==1.0.2 python-multipart==0.0.5 MySQLを環境に加える docker-compose.ymlを加えていきます。 MySQLの設定は下記のサイトを参考にしています。 https://qiita.com/ucan-lab/items/b094dbfc12ac1cbee8cb docker-compose.yml version: "3" services: db: image: mysql:8.0 volumes: - db-store:/var/lib/mysql - ./logs:/var/log/mysql - ./docker/mysql/my.cnf:/etc/mysql/conf.d/my.cnf environment: - MYSQL_DATABASE=${DB_NAME} - MYSQL_USER=${DB_USER} - MYSQL_PASSWORD=${DB_PASS} - MYSQL_ROOT_PASSWORD=${DB_PASS} - TZ=${TZ} ports: - ${DB_PORT}:3306 web: build: . ports: - 80:80 command: /start-reload.sh volumes: - ./app:/app environment: - DB_NAME=${DB_NAME} - DB_USER=${DB_USER} - DB_PASS=${DB_PASS} - DB_PORT=${DB_PORT} - DB_HOSTNAME=db volumes: db-store: docker/mysql/my.cnf # MySQLサーバーへの設定 [mysqld] # 文字コード/照合順序の設定 character-set-server = utf8mb4 collation-server = utf8mb4_bin # タイムゾーンの設定 default-time-zone = SYSTEM log_timestamps = SYSTEM # デフォルト認証プラグインの設定 default-authentication-plugin = mysql_native_password # エラーログの設定 log-error = /var/log/mysql/mysql-error.log # スロークエリログの設定 slow_query_log = 1 slow_query_log_file = /var/log/mysql/mysql-slow.log long_query_time = 5.0 log_queries_not_using_indexes = 0 # 実行ログの設定 general_log = 1 general_log_file = /var/log/mysql/mysql-query.log # mysqlオプションの設定 [mysql] # 文字コードの設定 default-character-set = utf8mb4 # mysqlクライアントツールの設定 [client] # 文字コードの設定 default-character-set = utf8mb4 DB_NAME=homestead DB_USER=homestead DB_PASS=secret DB_PORT=3306 TZ=Asia/Tokyo ディレクトリ構成はこうなったはずです。 . ├── Dockerfile ├── app │ └── requirements.txt ├── docker │ └── mysql │ └── my.cnf └── docker-compose.yml アプリケーションを書く appフォルダ以下にmain.pyを加えていきます。 app/main.py from fastapi import FastAPI app = FastAPI() @app.get("/") async def root(): return {"message": "Hello World"} ディレクトリ構成です。 . ├── Dockerfile ├── app │ ├── app.py │ └── requirements.txt ├── docker │ └── mysql │ └── my.cnf └── docker-compose.yml 起動 起動していきましょう。 docker-compose up しばらくすると下記のような表示が出るはずです。 web_1 | INFO: Uvicorn running on http://0.0.0.0:80 (Press CTRL+C to quit) web_1 | INFO: Started reloader process [1] using watchgod web_1 | INFO: Started server process [8] web_1 | INFO: Waiting for application startup. web_1 | INFO: Application startup complete. http://0.0.0.0:80 にアクセスすると下記のレスポンスが得られるはずです。 {"message":"Hello World"} http://0.0.0.0:80/docs にアクセスするとSwagger的なドキュメントを見ることができます。 データベース連携 appフォルダ以下に database.py というファイルを追加します。 MySQLと接続するために必要です。 app/database.py import os from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker user = os.getenv("DB_USER") password = os.getenv("DB_PASS") dbname = os.getenv("DB_NAME") hostname = os.getenv("DB_HOSTNAME") SQLALCHEMY_DATABASE_URL = f"mysql+pymysql://{user}:{password}@{hostname}/{dbname}" engine = create_engine(SQLALCHEMY_DATABASE_URL) SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) Base = declarative_base() appフォルダ以下に models.py というファイルを追加します。 テーブルの定義をします。 app/models.py from sqlalchemy import Boolean, Column, Integer, String from sqlalchemy.orm import relationship from database import Base class User(Base): __tablename__ = "users" id = Column(Integer, primary_key=True, index=True) username = Column(String(120), index=True) full_name = Column(String(120)) email = Column(String(200), unique=True, index=True) hashed_password = Column(String(60)) disabled = Column(Boolean, default=True) app/main.pyに下記を足します。 本来ならばcreate_allは利用せずにmigrationツールを使いますので注意してください。 models.Base.metadata.create_all(bind=engine) app/main.py from fastapi import FastAPI import models from database import engine models.Base.metadata.create_all(bind=engine) app = FastAPI() @app.get("/") async def root(): return {"message": "Hello World"} このままだとMySQLが起動する前にFastAPIサーバーが起動してしまうので起動を待つようにします。 prestart.shというファイルをapp配下に置きます。 app/prestart.sh #! /usr/bin/env bash # Let the DB start sleep 10; 再度起動するとデータベースにテーブルが作成されます。 OAuth2認証とJWT 下記の内容になります。 https://fastapi.tiangolo.com/tutorial/security/oauth2-jwt/ app/main.pyに書き足していきます。 app/main.py from datetime import datetime, timedelta from typing import Optional from fastapi import Depends, FastAPI, HTTPException, status from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm from jose import JWTError, jwt from passlib.context import CryptContext from pydantic import BaseModel from sqlalchemy.orm import Session import models from database import engine, SessionLocal SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7" ALGORITHM = "HS256" ACCESS_TOKEN_EXPIRE_MINUTES = 30 class Token(BaseModel): access_token: str token_type: str class TokenData(BaseModel): username: Optional[str] = None class User(BaseModel): username: str email: Optional[str] = None full_name: Optional[str] = None disabled: Optional[bool] = None class UserInDB(User): hashed_password: str models.Base.metadata.create_all(bind=engine) pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") app = FastAPI() def get_db(): db = SessionLocal() try: yield db finally: db.close() def verify_password(plain_password, hashed_password): return pwd_context.verify(plain_password, hashed_password) def get_password_hash(password): return pwd_context.hash(password) def get_user(db, username: str): return db.query(models.User).filter(models.User.username == username).first() def authenticate_user(db, username: str, password: str): user = get_user(db, username) if not user: return False if not verify_password(password, user.hashed_password): return False return user def create_access_token(data: dict, expires_delta: Optional[timedelta] = None): to_encode = data.copy() if expires_delta: expire = datetime.utcnow() + expires_delta else: expire = datetime.utcnow() + timedelta(minutes=15) to_encode.update({"exp": expire}) encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM) return encoded_jwt async def get_current_user(token: str = Depends(oauth2_scheme), db: Session = Depends(get_db)): credentials_exception = HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Could not validate credentials", headers={"WWW-Authenticate": "Bearer"}, ) try: payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM]) username: str = payload.get("sub") if username is None: raise credentials_exception token_data = TokenData(username=username) except JWTError: raise credentials_exception user = get_user(db, username=token_data.username) if user is None: raise credentials_exception return user @app.post("/token", response_model=Token) async def login_for_access_token(form_data: OAuth2PasswordRequestForm = Depends(), db: Session = Depends(get_db)): user = authenticate_user(db, form_data.username, form_data.password) if not user: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Incorrect username or password", headers={"WWW-Authenticate": "Bearer"}, ) access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES) access_token = create_access_token( data={"sub": user.username}, expires_delta=access_token_expires ) return {"access_token": access_token, "token_type": "bearer"} @app.get("/") async def root(current_user: User = Depends(get_current_user)): return {"message": "Hello World"} データベースのusersに下記のレコードを追加します。 id username full_name email hashed_password disabled 1 johndoe John Doe johndoe@example.com $2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW 使い方 http://localhost:docs に繋ぎましょう。 / Root を開いて「Try it out」押し、Executeボタンを押すと401 Unauthorizedが返ってくるのが確認できます。 右上のAuthorizeボタンを押すと認証フォームが表示されるので、usernameに「johndoe」、passwordに「secret」と入力して「Authorize」ボタンを押します。 再度、/Root を開いて先程と同じ操作をすると、今度はHTTP200が返ってきます。 ハマりどころ SQLAlchemyとMySQLが意外とセットアップ難しい。 FastAPIのドキュメントで認証のバックエンドがフェイクなのでDBとの連携する箇所が分かりづらい。 pydanticのスキーマとSQLAlchemyのスキーマとリクエストのスキーマの3種類のスキーマが存在するのが分かりづらい。 参考サイト uvicorn-gunicorn-fastapi-docker https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker MySQL8.0のコンテナ作成 https://qiita.com/ucan-lab/items/b094dbfc12ac1cbee8cb
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ECSのタスク定義で環境変数をS3から取得しようとしてハマったポイント

やりたかった事 { "family": "", "containerDefinitions": [ { "name": "", "image": "", ... "environment": [ { "name": "variable", "value": "value" } ], ... } ], ... } こんな感じで定義していた環境変数をS3バケットに入れた.envファイルから取得したい。 公式ドキュメントをみるとenvironmentFilesっていうのでいけそう。 やってみる ECSで紐づけていたIAMロールに別途S3へのアクセスを付与する必要がある。 ここは本題ではないので割愛。こちらの記事を参考にする。 最初IAMロールにS3の権限なくて怒られたけど、↑を参考にやったら怒られなくなった。 しかしログを確認してみると。migrationでこけてる。。なぜだ。。 原因 タスク定義で指定する環境変数はenvironment→environmentFilesの優先順位で動いている。 つまりenvironmentで指定していると上書きしてしまう挙動だった。 間違い "containerDefinitions": [ { ... "environmentFiles": [ { "value": "arn:aws:s3:::sample-bucket/prod.env", "type": "s3" } ], "environment": [], ... } ] 正しい "containerDefinitions": [ { ... "environmentFiles": [ { "value": "arn:aws:s3:::sample-bucket/prod.env", "type": "s3" } ], "environment": null, ... } ] "environment": nullにする事で上書きされる事なくmigration実行されるようになった。 どうやらDockerの仕様らしい ECSのタスク定義で設定したenvironmentとenvironmentFilesは以下のように対応している(はず)。認識間違ってたらコメントください。 environment environmentFiles docker run --env docker run --env-file docker run --env 'HOGE=hoge' --env-file='prod.env' こうした場合は--envでの指定が優先される。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

dockerとcloudflareを使ってWebサイトを簡単にSSL化対応(ワイルドカード証明書) & 面倒な証明書更新も自動化してみた

Chromeでhttpサイトが見れなくなる?? Chromeの開発元であるGoogleは以下のような声明を出しました。 (引用元: https://security.googleblog.com/2019/10/no-more-mixed-messages-about-https_3.html) Today we’re announcing that Chrome will gradually start ensuring that https:// pages can only load secure https:// subresources. In a series of steps outlined below, we’ll start blocking mixed content (insecure http:// subresources on https:// pages) by default. This change will improve user privacy and security on the web, and present a clearer browser security UX to users. 本日、Chrome では、https:// ページが安全な https:// サブリソースのみを読み込むことができるようにすることを段階的に開始することを発表しました。以下に概説する一連の手順で、混合コンテンツ ( https:// ページの安全でない http:// サブリソース) をデフォルトでブロックするようになります。この変更により、ウェブ上でのユーザーのプライバシーとセキュリティが改善され、より明確なブラウザセキュリティUXをユーザーに提示することができます。 混合コンテンツ 混合コンテンツとは、https内に存在するhttpなコンテンツのことを指します。 つまり「https://xxxxxxxxx.com/」というセキュアなサイト内で「http://yyyyyyyyyyy.com/image/test.png」のようなセキュアでないコンテンツを呼び出している状態を意味します。 つまり、httpなサイトはChromeで閲覧できなくなる可能性があるということです。 さらにこの問題が顕著なのは、日本におけるChromeの利用率が高いという点です。 (参照元: https://lab.syncer.jp/Statistic/Browser/2019/10/) ・ デスクトップのシェア:66.14%(1位) ・ モバイルのシェア:26.46%(2位) ・ タブレットのシェア:36.56%(2位) 社内だけのサービス(退勤管理やソース管理など)だからといって、セキュア化していないとアクセスできない。なんてことにならないように社内のネットワーク整備をすることにしました。 では、社会人1年目、新卒入社の筆者が社内ネットワーク整備に奮闘した一部始終をどうぞ!! 環境 CentOS 7 → 社内サービスがDocker on CentOS7で動いてた Let's Encrypt → 無料で使えるSSL証明書。90日で期限が切れるため更新が必須 Cloudflare → ワイルドカード証明書を発行するのにDNSレコードを変更する必要があるため、無料で使えるCloudflareを採用。(このためだけにNSを変更したといっても過言ではない) lego(https://go-acme.github.io/lego/) → Let's Encryptの環境がさくっと作れるDocker環境。大体のDNS Providerに対応してて、それぞれの設定方法や実行方法が書いてあってありがたい。 (対応してるDNS Provider一覧はこちら) 改修フロー https化へのざっくりとしたフローはこちらです。 社内サービスへのアクセスをサブドメインで行えるようにする → いままではIPアドレス、ポート指定のアクセスだったので、サービスが増えると何かと面倒 ドメインのネームサーバー(NS)をCloudflareに変更 → 現在運用していたところではDNSレコードの書き換えが制限されていた & API経由での書き換えができなかったため Cloudflareでソーン編集用APIアクセスキーを作成 社内サービスコンテナ内で自動更新スクリプト等の作成 Nginxなどに証明書を食わせる 今回は検証用の個人的なドメイン(choipre.com)(Google Domains)を使って解説します。 ドメイン取ったけど、個人サービスが完成していないので、何しても大丈夫だし。 !! 注意 !! 設定を間違えるとサイトにアクセスできなくなったりする可能性があります。必ず変更点(Diff)などはメモするようにしておいた方が、万が一のためです。バックアップなどを取りつつ作業を進めることをおすすめします。 1. 社内サービスへのアクセスをサブドメインで行えるようにする これまで、社内サービスにはIPアドレスを使ってアクセスしていました。そのためhttps化できず、httpな状態で運用していました。まずは、社内サービスへのアクセスをサブドメインでアクセスできるようにするため、社内DNSを整備します。ドメインは、会社HPなどで元々利用しているものを利用しました。 社内だけで使えるサービスやシステムを複数運営していると、IPアドレスでのアクセスは大変になってきます。 そこで、社内サービスにもドメインを使ってアクセスできるように社内DNSを整備しました。 前提 ドメインは取得済み 取得ドメイン:choipre.com 構築後のネットワーク図は以下のような感じになります 構築 DNSはDockerを使って構築します。CoreDnsというDocker-imageが公開されているので、そちらを利用します。フォルダ構成としては以下の感じです。 drwxr-xr-x - nomunomu 2 11 18:01 dns .rw-r--r-- 244 nomunomu 4 11 16:00 ├── docker-compose.yml .rw-r--r-- 115 nomunomu 4 11 16:00 ├── Dockerfile drwxr-xr-x - nomunomu 2 11 17:58 └── volumes drwxr-xr-x - nomunomu 4 11 16:14 └── config .rw-r--r-- 181 nomunomu 4 11 16:32 ├── Corefile .rw-r--r-- 53 nomunomu 4 11 16:14 └── hosts Docker系設定 docker-compose.yml version: '3.1' services: coredns: build: . container_name: coredns restart: on-failure expose: - '53' - '53/udp' ports: - '53:53' - '53:53/udp' volumes: - './volumes/config:/etc/coredns' Dockerfile FROM coredns/coredns:1.7.0 EXPOSE 53 EXPOSE 53/udp ENTRYPOINT ["/coredns"] CMD ["-conf", "/etc/coredns/Corefile"] CoreDns設定 どのドメインとIPアドレスが紐づくかをhostsファイルに記述します。Corednsの設定はファイルはCorefileというファイルに記述します。 Corefile . { whoami forward . 192.168.0.100:53 # ここはPublic-DNSでもよい errors log . "{proto} {remote} is Request: {name} {type} {>id}" hosts /etc/coredns/hosts { fallthrough } reload } hosts 192.168.0.110 xxxxxx.choipre.com 192.168.0.111 yyyyyy.choipre.com 192.168.0.112 zzzzzz.choipre.com 起動 docker-compose.ymlがあるディレクトリで以下のコマンドを流すと、DNSが起動します。 $ docker-compose up docker-composeを走らせたPC(192.168.0.100)へ各クライアントのDNS解決先を向けることでローカルのIPに対してもドメインでアクセスすることができるようになります。 2. ドメインのネームサーバー(NS)をCloudflareに移行する なぜNSをCloudflareに変更したかというと、CloudflareではAPIを使ってドメインのゾーン情報(A, AAAA, TXTなどのDNSレコード情報)を書き換えることができます。 (参考: https://api.cloudflare.com/#zone-subscription-zone-subscription-details) この仕組みを利用して、スクリプト上でワイルドカードのSSL証明書を発行するのに必要なレコード内容を自動で書き込みたかったからです。 (証明書更新する度に手動でDNSレコードに追記したり、削除したりするのって面倒だし、ネットワークの知識がない人が更新しないといけないってなったときに、このコマンド一発叩けばいいよ!の方がいいよね?) Cloudflareにドメインを登録 Cloudflareのアカウントを持っていない人はアカウント作成してください。 アカウント作成後、トップ画面に 【サイトを追加する】 を押します。 (※ 画像は既に登録済みのドメインがあるため、Cloudflareの管理下にあるドメイン一覧がありますが、初期登録後の人は何も表示されていません。) Cloudflareで管理したいドメインを入力します。 プラン選択画面が表示されるので 【Freeプラン】 を選択します。 (Freeプランでここまで出来るってCloudflare様様...) Cloudflareに既存DNSレコードを移植 ドメインの登録が完了すると、現在設定されているDNSレコードを読み取って、Cloudflareに書き込み準備をしてくれます。このときにDNSレコードを修正することもできますが、必要がない人はそのまま 【続行】 します。 ただし、AレコードとMXレコードが同一の場合、AレコードをCloudflareのプロキシから外す必要があります。プロキシから外してDNS解決のみにしないとメールサーバーが正常に動作しないためです。 (参考: Cloudflareの使用時にメールが配信不能になる - メール関連のDNSレコード) CloudflareのNSに変更する Cloudflareに取り込むDNSレコードの設定が終わったら、ドメインのNSをCloudflareに変更するように促されます。 各ドメインの管理画面からドメインのNSを変更します。今回の検証用ドメインはGoogle Domainsで取得しているため、Google Domainsの設定画面から変更します。 ドメインのNS変更が終わったら、Cloudflareで引き続き設定を行います。ここでは、ドメインへのアクセス、コンテンツのキャッシュ・圧縮設定ができます。利用に応じた設定を行ってください。 検証用ドメインでは、以下のように設定しました。 Cloudflare-NSの変更チェック 次にNSレコードのチェックをします。既にNSの変更が検知できている場合は、以下のような表示になります。 まだ、検知できていない場合は以下のような表示になります。ドメインの設定がネットワーク全体に浸透するまでは24~48時間程かかります。Cloudflareでチェックしても変更されていなかった場合は、少し時間をおいてください。ちなみに、Cloudflareで正常にNSが変更されていることを検知すると、アカウント登録時に設定したメールアドレスに通知がきます。 3. ゾーン編集用APIアクセスキーを作成 legoのライブラリを利用するために必要な、CloudflareのDNSゾーン情報APIアクセスキーを作成します。キーは2種類作成します。 ゾーン情報の【DNS編集キー】と【ゾーン編集キー】です。Cloudflareのアカウント設定のAPIトークンから作成することができます。 まず、APIアクセスキーを作成する前に、画面下部にある「Global Api key」も取得しておきましょう。4.のdocker-compose.ymlに記述する必要があるためです。 アクセスキーを作成する際に、いくつかテンプレートが用意されています。今回は【ゾーンDNSを編集する】というテンプレートを編集して利用します。テンプレートを利用せずに0から作成することもできますが、慣れてから使うか、似たテンプレートを変更したほうが無難そうです。 1つのトークンに対して、複数の権限を付与することができますが、トークンが増えてくると管理がしづらくなるので、1トークン1権限で運用することとします。アクセス許可に以下を、それぞれ設定して2つのトークンを作成します。 1つ目のトークン → ゾーン:DNS:編集 2つ目のトークン → ゾーン:ゾーン:編集 2つの共通設定(ゾーンリソース) → 包含:特定のゾーン:ワイルドカード証明書を発行したいドメイン トークン作成を進めると、以下のような画面が表示されます。このときに表示されるトークンをメモしてください。ここで表示されたトークンは、画面にもあるように再表示されません。そのため、必ずメモするようにしてください。メモし忘れたら、APIトークンを削除して、再作成してください。 4. SSL証明書の自動更新スクリプトをdocker-composeサービスとして作成 会社の社内サービスが動いているDockerでは、以下のような運用がされています。 平日(月〜金)は昼夜問わず常時起動 休日(土日)に自動シャットダウン 月曜にサービスを立ち上げる このことから、サービスを立ち上げるときにSSL証明書の更新処理を走るようにしておけば、最低週に1回は確認することになり、更新忘れによる証明書失効を防ぐことが出来ると考えました。サービス自体がDockerで運用されているため、SSL更新処理もDocker化して、Serviceとして登録する方向にしました。 lego(https://go-acme.github.io/lego/)を使ったSSL証明書更新用Dockerは以下のように設定しました。 docker-compose.yml services: certbot-lego: image: goacme/lego:latest environment: - CLOUDFLARE_API_EMAIL=[Cloudflareで登録したメールアドレス] - CLOUDFLARE_API_KEY=[3.で取得したGlobal Api Key] - CLOUDFLARE_DNS_API_TOKEN=[3.で作成したゾーン:DNS編集APIキー] - CLOUDFLARE_ZONE_API_TOKEN=[3.で作成したゾーン:ゾーン編集APIキー] command: > --path /lego --dns cloudflare # 利用しているDNSプロバイダに書き換えてください --dns.resolvers 8.8.8.8 # DNSレコードが伝搬していない可能性があるのでパブリックDNSで解決させる --email [Cloudflareで登録したメールアドレス] --domains "*.choipre.com" # 適宜置き換えてください --domains "choipre.com" # 適宜置き換えてください --accept-tos run volumes: - /opt/cert:/lego # /opt/cert 配下に証明書等が吐き出されます。適宜書き換えてください docker-compose.yml を作成して、docker-composeを実行します。 $ docker-compose up 実行が終わると、以下のようなログが流れ、/opt/cert 配下に証明書本体が格納されているディレクトリと、更新に必要なアカウント情報が含まれているディレクトリが生成されます。 ❯ docker-compose up Recreating certbot-cloudflare_certbot-lego_1 ... done Attaching to certbot-cloudflare_certbot-lego_1 certbot-lego_1 | 2020/11/28 06:44:01 [INFO] acme: Registering account for [Cloudflareに登録したメールアドレス] certbot-lego_1 | !!!! HEADS UP !!!! certbot-lego_1 | certbot-lego_1 | Your account credentials have been saved in your Let's Encrypt certbot-lego_1 | configuration directory at "/lego/accounts". certbot-lego_1 | certbot-lego_1 | You should make a secure backup of this folder now. This certbot-lego_1 | configuration directory will also contain certificates and certbot-lego_1 | private keys obtained from Let's Encrypt so making regular certbot-lego_1 | backups of this folder is ideal. certbot-lego_1 | 2020/11/28 06:44:01 [INFO] [*.choipre.com, choipre.com] acme: Obtaining bundled SAN certificate certbot-lego_1 | 2020/11/28 06:44:03 [INFO] [*.choipre.com] AuthURL: https://acme-v02.api.letsencrypt.org/acme/authz-v3/8920315819 certbot-lego_1 | 2020/11/28 06:44:03 [INFO] [choipre.com] AuthURL: https://acme-v02.api.letsencrypt.org/acme/authz-v3/8920315820 certbot-lego_1 | 2020/11/28 06:44:03 [INFO] [*.choipre.com] acme: use dns-01 solver certbot-lego_1 | 2020/11/28 06:44:03 [INFO] [choipre.com] acme: Could not find solver for: tls-alpn-01 certbot-lego_1 | 2020/11/28 06:44:03 [INFO] [choipre.com] acme: Could not find solver for: http-01 (省略) certbot-lego_1 | 2020/11/28 06:44:11 [INFO] [*.choipre.com, choipre.com] acme: Validations succeeded; requesting certificates certbot-lego_1 | 2020/11/28 06:44:12 [INFO] [*.choipre.com] Server responded with a certificate. certbot-cloudflare_certbot-lego_1 exited with code 0 drwxr-xr-x - nomunomu 28 11 15:43 └── opt drwxr-xr-x - nomunomu 28 11 15:44 └── cert drwx------ - nomunomu 28 11 15:43 ├── accounts drwx------ - nomunomu 28 11 15:43 │ └── acme-v02.api.letsencrypt.org drwx------ - nomunomu 28 11 15:44 │ └── xxxxxxxxxxx@gmail.com .rw------- 225 nomunomu 28 11 15:44 │ ├── account.json drwx------ - nomunomu 28 11 15:43 │ └── keys .rw-r--r-- 227 nomunomu 28 11 15:43 │ └── xxxxxxxxxx@gmail.com.key drwx------ - nomunomu 28 11 15:44 └── certificates .rw------- 3.3k nomunomu 28 11 15:44 ├── _.choipre.com.crt .rw------- 1.6k nomunomu 28 11 15:44 ├── _.choipre.com.issuer.crt .rw------- 234 nomunomu 28 11 15:44 ├── _.choipre.com.json .rw------- 227 nomunomu 28 11 15:44 └── _.choipre.com.key この生成されたフォルダで、accountsフォルダは今後証明書を更新していくなかで必要になるフォルダです。証明書類はcertificatesに保管されています。 「_.choipre.com.crt」がchoipre.comのワイルドカード証明書になります。 一度、証明書発行を実行したので、今後は更新という処理を行う設定にしておく必要があります。そのため、docker-compose.ymlを以下のように変更します。 docker-compose.yml services: certbot-lego: image: goacme/lego:latest environment: - CLOUDFLARE_API_EMAIL=[Cloudflareで登録したメールアドレス] - CLOUDFLARE_API_KEY=[3.で取得したGlobal Api Key] - CLOUDFLARE_DNS_API_TOKEN=[3.で作成したゾーン:DNS編集APIキー] - CLOUDFLARE_ZONE_API_TOKEN=[3.で作成したゾーン:ゾーン編集APIキー] command: > --path /lego --dns cloudflare # 利用しているDNSプロバイダに書き換えてください --dns.resolvers 8.8.8.8 # DNSレコードが伝搬していない可能性があるのでパブリックDNSで解決させる --email [Cloudflareで登録したメールアドレス] --domains "*.choipre.com" # 適宜置き換えてください --domains "choipre.com" # 適宜置き換えてください --accept-tos renew --days 30 volumes: - /opt/cert:/lego # /opt/cert 配下に証明書等が吐き出されます。適宜書き換えてください 変更点は、run から renew コマンドに変更することです。パラメーターとして --days を指定することで指定した日数を切ってから更新させることができます。 この、docker-composeの実行をcronなどに設定することで自動更新を行えるようになります。 5. 発行した証明書をNginxに適用してhttps化 4.で生成した証明書をNginxに適用していきます。証明書類は/opt/cert配下にあるものとします。 Nginxの設定ファイルに以下の記述を追記します。追記場所はNginxの設定ファイルの使用したいServer設定の中です。デフォルト構成を利用している人は server{ ... } の中に追記します。 ssl_certificate /opt/cert/_.choipre.com.crt; ssl_certificate_key /opt/cert/_.choipre.com.key; 記述ができたら、Nginxのプロセスを再起動します。Nginxのプロセスを再起動したら、対象のアドレスに対してhttpsアクセスをすると証明書が適用されていることが分かります。 まとめ 以上で、自動更新可能なワイルドカード証明書発行の実装が終わりました。 初期設定は大変ですが、今後はあらゆるサブドメインに対してSSL通信を行うことができます。これでChromeでhttpコンテンツが閲覧できなくなっても、安心ですね。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Docker】Quickstart : Compose and Rails やってみた

概要 DockerでRails5に対応したRuby on Railsの環境構築を行いました。 このクィックスタートでは Docker Compose を使って、 簡単な Rails/PostgreSQL アプリを設定することができます。 学んだ一連の流れをまとめておきます。 (一番下にDockerのコマンド一覧も掲載しております!) 前提としてDockerとcomposeのインストールができている状態とします。 まだの人はこちらを参考にして下さい。 ・【図解】Dockerの全体像を理解する -前編- ・いまさらだけどDockerに入門したので分かりやすくまとめてみた ・【入門】はじめての Docker Desktop for Mac のインストールと CentOS の仮想環境構築のセットアップ 環境 ・MacOS Apple M1 バージョン11.4 ・Docker 20.10.7 ・Ruby 2.5.9 ・Rails 5.2.6 ー参考資料ー ・公式ドキュメントQuickstart: Compose and Rails ・クィックスタート: Compose と Rails ・DockerのQuickstart:Compose and Railsをやってみた 手順 インストールができている確認 docker % docker version Client: Cloud integration: 1.0.17 Version: 20.10.7 API version: 1.41 Go version: go1.16.4 Git commit: f0df350 Built: Wed Jun 2 11:56:23 2021 OS/Arch: darwin/arm64 Context: default Experimental: true Server: Docker Engine - Community Engine: Version: 20.10.7 API version: 1.41 (minimum version 1.12) Go version: go1.13.15 Git commit: b0f5bc3 Built: Wed Jun 2 11:55:36 2021 OS/Arch: linux/arm64 Experimental: false containerd: Version: 1.4.6 GitCommit: d71fcd7d8303cbf684402823e425e9dd2e99285d runc: Version: 1.0.0-rc95 GitCommit: b9ee9c6314599f1b4a7f497e1f1f856fe433d3b7 docker-init: Version: 0.19.0 GitCommit: de40ad0 dockercompose % docker compose Docker Compose version v2.0.0-beta.6 Dockerを使ったRuby on Railsの環境構築 Dockerとcomposeのインストールが完了したのでDockerを用いたRuby on Railsの環境構築を行います。 DockerでRuby on Railsの環境を構築するプロジェクトのディレクトリを作成し移動します。 今回はmyappとします。 % cd myapp 4つのファイルを準備 ⑴ docker-compose.yml ⑵ Dockerfile ⑶ Gemfile ⑷ Gemfile.lock ⑴ docker-compose.yml docker-compose.ymlというファイル名をVScodeに作成します。 以下を記述↓↓ docker-compose.yml version: '3' services: db: image: postgres environment: - POSTGRES_PASSWORD=password web: build: . command: bundle exec rails s -p 3000 -b '0.0.0.0' volumes: - .:/myapp ports: - "3000:3000" depends_on: - db ⑵ Dockerfile 次に、Dockerfileというファイル名をVScodeに作成します。 以下を記述↓↓ Dockerfile FROM ruby:2.5 RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs RUN mkdir /myapp WORKDIR /myapp ADD Gemfile /myapp/Gemfile ADD Gemfile.lock /myapp/Gemfile.lock RUN bundle install ADD . /myapp これでDockerを動かす記述が完了しました。 ⑶ Gemfile 次に、Gemfileというファイル名をVScodeに作成します。 以下を記述↓↓ Gemfile source 'https://rubygems.org' gem 'rails', '5.2.6' ⑷ Gemfile.lock 次に、Gemfile.lockというファイル名をVScodeに作成します。 この時、Gemfile.lockは空にしておきます。 Gemfile.lock # 記述なし これで4つのファイルの作成が完了しました。 上記4つのファイルを作ったうえで、コマンドをうっていきます。 % docker-compose build これでDockerfileのファイル内の記述を実行します。 次に以下のコマンドでrails new をします。 % docker-compose run web rails new . --force --database=postgresql これでダウンロードが完了したら、次にGemfileが更新されたので 再度以下のコマンドを実行します。 % docker-compose build Ruby on RailsのDB設定 config/database.yml を以下に書き換えます。 config/database.yml default: &default adapter: postgresql encoding: unicode host: db username: postgres password: password pool: 5 development: <<: *default database: myapp_development test: <<: *default database: myapp_test production: <<: *default database: myapp_production username: myapp password: <%= ENV['MYAPP_DATABASE_PASSWORD'] %> DBを作成 次に書き換えたDBを作成します。 % docker-compose run web rails db:create コンテナを起動 最後にコンテナを起動させます。 % docker-compose up http://localhost:3000/ にアクセスします。 この画面が出てきたら成功です! これでDockerでRuby on Railsの環境構築が完了です! 簡単な Rails/PostgreSQL アプリを設定することができました! 以下はDokerの開発に必要なコマンド一覧を残しておきます。 Dockerで使用するコマンド一覧 コマンド 動作 補足 docker ps   稼働コンテナの一覧表示 docker ps -a すべてのコンテナを表示 docker run コンテナの生成/起動 docker stats コンテナの稼働確認 docker start コンテナの起動 docker stop コンテナの停止 docker restart コンテナの再起動 docker rm コンテナの削除 docker pause コンテナの中断/再開 docker version   Dockerのバージョン確認 docker info Dockerの実行環境確認 docker commit コンテナからイメージ作成 docker save イメージの保存 docker build -t DockerfileからDockerイメージの作成 docker ls   ファイル変更 docker images ファイル変更 docker ps   ファイル変更 docker ps   ファイル変更 docker ps   ファイル変更 docker ps   ファイル変更 以上となります。 Dockerコマンドはまだまだたくさんあります。 今後、Dockerの開発が進むにつれて、都度更新していきます。 学習頑張っていきましょう!!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

DockerでPython3 - 実務編

ひとしきり、最低限の手順です。 準備 Docker for windows desktop等 (記事末尾参照) ├ Readme.md ├ Dockerfile ├ docker-compose.yml └ opt ├ foo.py └ bar.py docker-compose.yml docker-compose.yml version: '3' services: python3: restart: always build: . container_name: 'python3' working_dir: '/root/' tty: true volumes: - ./opt:/root/opt Dockerfile FROM python:3 USER root RUN apt-get update RUN apt-get -y install locales && \ localedef -f UTF-8 -i ja_JP ja_JP.UTF-8 ENV LANG ja_JP.UTF-8 ENV LANGUAGE ja_JP:ja ENV LC_ALL ja_JP.UTF-8 ENV TZ JST-9 ENV TERM xterm RUN apt-get install -y vim less RUN pip install --upgrade pip RUN pip install --upgrade setuptools RUN pip install psycopg2 RUN pip install svn RUN pip install requests コンテナ起動 docker-compose up -d --build コンテナへ接続 docker-compose exec python3 bash installされているもの確認 root@c75334aa5328:~/opt# python -m pip list Package Version ------------------ --------- certifi 2021.5.30 charset-normalizer 2.0.3 idna 3.2 nose 1.3.7 pip 21.1.3 psycopg2 2.9.1 python-dateutil 2.8.2 requests 2.26.0 setuptools 57.2.0 six 1.16.0 svn 1.0.1 urllib3 1.26.6 wheel 0.36.2 Python プログラム実行 python3 foo.py など。 Enjoy! コンテナが要らなくなったら... 下記で削除する。 docker-compose down 参考 Docker Desktop Python3 以上参考になればさいわいです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む