gitでリモートにpushするとerror: failed to push some refs toが表示される
環境
- macOS 10.14.6
- git 2.23.0
事象
ローカルブランチにfeature/#7_test
を作成し、コミット後にリモートへpushした際に以下エラーが発生
$ git push origin feature/#7_test Enumerating objects: 5, done. Counting objects: 100% (5/5), done. Delta compression using up to 4 threads Compressing objects: 100% (3/3), done. Writing objects: 100% (3/3), 335 bytes | 335.00 KiB/s, done. Total 3 (delta 1), reused 0 (delta 0) remote: Resolving deltas: 100% (1/1), completed with 1 local object. To https://github.com/seiya2130/git_tutorial.git ! [remote rejected] feature/#7_test -> feature/#7_test (cannot lock ref 'refs/heads/feature/#7_test': 'refs/heads/feature' exists; cannot create 'refs/heads/feature/#7_test') error: failed to push some refs to 'https://github.com/seiya2130/git_tutorial.git'
原因
- リモート追跡ブランチに
remotes/origin/feature
が残っていたため
ブランチ名で/(スラッシュ)が使われている場合、スラッシュ内で同名の単語があるとpush出来ない。
git branch -a
でブランチを確認すると、リモート追跡ブランチにremotes/origin/feature
があった。
$ git branch -a * feature/#7_test feature/test master remotes/origin/HEAD -> origin/master remotes/origin/feature remotes/origin/master remotes/origin/test
今回作成したブランチであるfeature/#7_test
のfeature
の部分が一致してしまい、pushが出来なかった
(同ディレクトリの中に同名フォルダが作れないようなイメージ)
対応
- 不要なリモート追跡ブランチを削除し、pushする
-
git remote prune orign
でリモートブランチを削除する -
git push origin feature/#7_test
で再度pushする
-
参考
Docker/Kubernetes実践コンテナ入門 復習(2)
Dockerコンテナのデプロイ
コンテナでアプリケーションを実行する
- Dockerイメージ
- Dockerコンテナを構成するファイルシステム、実行するアプリケーションをまとめた、コンテナを作成するテンプレートとなるもの
- Dockerコンテナ
- Dockerイメージから作成され、具現化されたファイルシステムとアプリケーションが実行されている状態
簡単なアプリケーションとDockerイメージを作る
- DockerfileにはDocker独自のDSL(ドメイン固有言語)で構成を定義する
FROMやRUNはインストラクション(命令)と呼ばれる
FROM
- Dockerイメージのベースイメージを指定
- 取得するイメージはDocker Hubというホスティングサービスに公開されているもの
- タグを指定することで特定のバージョンのイメージを識別する
RUN
- Dockerイメージビルド時にDockerコンテナ内で実行するコマンド
COPY
- Dockerを動作させているホストマシンのファイルやディレクトリをDockerコンテナ内にコピーする
CMD
- Dockerコンテナとして実行する際に、コンテナ内で実行するプロセスを指定
- RUNでアプリケーションの更新や配置、CMDでアプリケーションそのものを動かす
Dockerイメージをビルドする
- Dockerイメージを
docker image build
によりビルドする-
docker image build -t イメージ名[:タグ名] Dockerfileディレクトリパス
-
- -tオプションとイメージ名なしだとハッシュ値で管理ことになるため、必ずつける
- イメージ名の衝突回避のため、名前空間をつけることを推奨
example/test
ENTRYPOINTでコマンドの実行の仕方を工夫する
- ENTRYPOINTはCMDと同じくコンテナ内で実行するプロセスを指定可能
- CMDの引数がENTRYPOINTで実行するファイルへの引数となる
- コンテナの用途を制限したい場合に使用する
Dockerコンテナを実行する
docker container run Dokerイメージ
- -dオプションでバックグラウンド実行
ポートフォワーディング
- ホストマシンのポートをコンテナポートに紐付け、コンテナの外からきた通信をコンテナポートに転送する(コンテナポートは通常ホストからアクセス不可のため)
-p ホスト側ポート:コンテナポート
Dockerイメージの操作
- Dockerの基本操作はイメージに関する操作かコンテナに関する操作
- DockerイメージはDockerコンテナを作成するテンプレート
- DockerfileからDockerイメージを構築することをDockeイメージをビルドするという
docker image build イメージのビルド
- Dockerfileを元にDockerイメージを作成する
- -tオプションはイメージ名・タグ名子弟のため必須
- -fオプションはデフォルトのDockerfile以外のファイルを使う
- --pullオプションはFROMで指定したイメージをレジストリから取得する(取得ずみでもベースイメージを再取得する)
docker search イメージの検索
- Docker hubではリポジトリでDockerイメージを管理している
docker search オプション 検索キーワード
で登録リポジトリを検索可能- 表示はSTARSの降順
- --limit オプションで表示数制限
docker image pull イメージの取得
- Dockerレジストリからイメージを取得
docker image pull リポジトリ[:タグ名]
- タグを省略した場合、デフォルトのタグが利用される
docker image ls イメージの一覧
- ホストに保持されているイメージの一覧を表示する
docker image ls リポジトリ[:タグ名]
- docker pull/docker image buildしたイメージ
- コンテナIDとイメージIDは別物
docker image tag イメージのタグ付け
- Dockerイメージの特定のバージョンにタグ付けする
Dockerイメージのバージョン
- Dockerイメージのバージョン=イメージID(バージョン番号)
イメージIDへのタグ付け
- タグはイメージIDを持つDockerイメージを識別するためのもの
- タグを指定しない場合はlatestのタグがつく
- ビルド後のイメージにもタグ付け可能
docker image tag 元イメージ名 新イメージ名
docker image push イメージの公開
- DockerイメージをDoceker Hubに登録する
docker image push リポジトリ名:[タグ]
- 公開リポジトリのため、パスワードなどの機密情報は含めないようにする
Dockerコンテナの操作
Dockerのライフサイクル
- コンテナは実行中、停止、破棄の状態がある
- 作成されたコンテナは同じイメージを利用していても個別に状態を持つ
実行中
- Dockerイメージからコンテナが作成され、CMDやENTRYPONTで定義したアプリケーションの実行を開始する
- アプリケーションが実行中ならコンテナは実行中にある
停止
- 明示的に停止するかコンテナのアプリが終了した場合に自動停止する
- ディスクにコンテナの状態は残るため、再実行可能
破棄
- 停止したコンテナは明示的に破棄しない限りディスクに残り続けるため、不要なコンテナは破棄する
- 一度作成されたコンテナは開始時間などが異なるため、同じ状態のコンテナは作成不可
docker container run コンテナの作成と実行
- イメージからコンテンを作成・実行する
docker container run イメージ名/イメージID コマンド コマンド引数
- コンテナに名前をつけることで開発時の検証でコンテナIDやコンテナ名を頻繁に確認せずに済む
docker container run --name コンテナ名 イメージ名
docker contailer ls コンテナの一覧
- 実行中および終了したコンテナの一覧を表示
docker container ls
- -qオプションでコンテナIDだけ取得
- -filterオプションでイメージ名指定など特定のコンテナだけ取得
- -aオプションで終了したコンテナも含め取得
docker container stop コンテナの停止
- 実行しているコンテナを終了する
docker container stop コンテナIDまたはコンテナ名
docker container restart コンテナの再起動
- 停止したコンテンを再起動する
docker container restart コンテナIDまたはコンテナ名
docker container rm コンテナの破棄
- 停止したコンテナを削除する
docker container rm コンテナIDまたはコンテナ名
- -fオプションで実行中のコンテンを強制削除が可能
docker container run --rm
で停止後に自動削除する
docker container logs 標準出力の取得
- Dockerコンテナの標準出力を表示
- コンテナ内のアプリケーションがファイル出力したログは確認できない
docker container log コンテナIDまたはコンテナ名
docker container exec 実行中コンテナでコマンド実行
- 実行中コンテナで任意のコマンド実行
docker container exec コンテナID/コンテナ名 コンテナ内で実行するコマンド
docker container cp ファイルのコピー
- コンテナ同士、ホストとコンテナでファイルをコピーする
- 主にデバッグで使用する
docker container cp コピー元 コピー先
運用管理向けコマンド
prune 破棄
- 実行していないコンテナやイメージを一括削除する
docker container prune
docker image prune
docker container stats 利用状況の取得
- コンテナ単位のシステムリソースの利用状況を表示
Docker Composeでマルチコンテナを実行する
docker-composeによるコンテナの実行
- yaml形式の設定ファイルで複数コンテナの実行を管理できる
- Dockerイメージのビルドも行い、実行もできる
- イメージを頻繁に更新する開発時には--buildオプションをつけることでイメージのビルドが必ず実行される
Docker/Kubernetes実践コンテナ入門 復習(1)
Dockerの基礎
Dockerとは
- コンテナ仮想化技術を実現するために実行される常駐アプリケーションとそれを操作するためのコマンドフロントインターフェース
- ローカルで環境のセットアップが出来ていれば、コマンド一つで環境構築が可能
- 仮想マシンより高速でローカル・サーバー間で環境を簡単に再現出来る
Dockerの基礎概念
コンテナ型仮想化技術
- コンテナ型仮想化技術はDocker登場前はLXC(Linux Container)が有名だった
- コンテナ型仮想化技術では仮想化ソフトなしでOSのリソースを隔離し仮想OSとするためオーバヘッドが少ない
- 仮想化ソフトを利用する場合はホストOS型の仮想化と呼び、オーバヘッドが大きくなりがち
アプリケーションにフォーカスしたDocker
- LXCでは別のLXCホストで実行しようとしてもLXCの設定差異によって動作しない場合があったため、アプリケーションのデプロイ・運用の観点で機能不足だった
- Dockerはコンテナの情報をコードで管理することで取得・配布が容易で再現性が保ちやすいなど、アプリケーションのデプロイにフォーカスした機能を持っている
- Dockerはコンテナに実行環境とアプリケーションを同梱しているため、実行環境の依存問題を解決出来る
Dockerを利用する意義
環境際問題からの脱却
- サーバーの環境差異によって同じ挙動にならないことがあるため、環境際を限りなく排除する必要がある
Infrastructure Code Immutable Infrastructure
- Infrastructure Code
- コードベースでインフラを管理する
- 手作業を介する余地を減らすことで、同じ構成のサーバーを再現しやすくする
- ただし冪等性(何度実行しても同じ結果が保証される)を保ち続けることは難しい
- Immutable Infrastructure
- ある地点のサーバーの状態を保存し複製可能にする考え方
- 正しくセットアップされた状態を常に使うことが出来る
- 既存のインフラをアップデートするのではなく、新しく作り直すため、冪等性を気にする必要がない
アプリケーションとインフラをセットで構築する
- 旧来はインフラとアプリのデプロイは分断された作業だったため、環境差異が生まれやすかった
- コンテナはOS(インフラ)とアプリをセットでビルドできるため、環境差異が生まれにくい
- 作成したDockerイメージは保存、再利用が可能なためポータビリティが高い
アプリケーションの構成管理のしやすさ
- 一定の規模のシステムは複数のアプリやミドルウェアが組み合わさっているため、システム全体の構成管理が必要
Dockerのコンテナオーケストレーションシステム
- 複数コンテナを利用したアプリの管理のためにDocker Composeというツールがある
- yamlファイルで実行するコンテナを定義したり、依存関係を定義して起動順を制御する
- Docker Swarmは複数のサーバーをまたいで複数のコンテナを管理できる(コンテナオーケストレーション)
本番環境に導入してこそのDocker
新しい開発スタイルへ
- Dockerの普及でインフラがコードレベルで簡単に修正できるようになった
- インフラエンジニアとサーバーサイドエンジニアの垣根がなくなりつつある
- 現代的な開発のためにフロントエンドやスマホアプリエンジニアにも必要な技術になりつつある
入門docker 復習(8)
プロダクションでの活用
プロダクションへの導入
ローカル環境のDocker化
- チームの開発環境を統一する
テスト/CIへの導入
- ステージングへの導入
- 本番前に動作確認する
- 本番への導入
Tips
docker-compose
環境変数への読み込み
- docker-composeの起動時に渡す
docker-compose up -e MYSQL_PASSWORD=mypassword
- docker-compose.yamlへ記述
version: '3.7' services: app: build: . + environment: + - MYSQL_PASSWORD=mypassword
- シェル変数から読み込み
version: '3.7' services: app: build: . environment: - - MYSQL_PASSWORD=mypassword + - MYSQL_PASSWORD=${MYSQL_PASSWORD}
$ export MYSQL_PASSWORD=mypassword $ docker-compose up
- ファイルから読み込む
version: '3.7' services: app: build: . - environment: - - MYSQL_PASSWORD=mypassword + env_file: + - .env
#.env MYSQL_PASSWORD=mypassword
$ docker-compose up
ホストとコンテナ間のファイル共有の速度向上
オプション
consistend(default)
- ホストとコンテナ間の一貫性を担保するオプション
- オーバーヘッドが大きいため、ファイルの更新が発生する場合は非推奨
cached
- ホストの更新を優先する
- サービスコードのようにホスト側で更新するケース
delegated
- コンテナ側の更新を優先する
- MYSWLのようにコンテナからホストへの書き込みしかしないケース
- コンテナ上からライブラリのインストールをするコマンド(
composer install
,npm install
)を使用する場合
標準入力を有効にする
- デバッグに使用したい場合、明示的に設定可能
services: rails: build: . + tty: true + stdin_open: true ports: - '3000:3000' volumes: - './:/app:cached'
Multi-Stage Buildのローカル活用
- 過去のレイヤーを使用したい場合、明示的に設定可能
ersion: '3.7' services: app: build: context: . + target: build volumes: - ./:/go/app command: go run main.go
docker-compose間のnetworkの共有
- マイクロサービス化によってフロントとバックバックエンドでリポジトリが異なる場合がある
- ネットワークを共有する必要がある
backend
- internalとexternalのネットワークを用意する
version: '3.7' services: api: build: . ports: - 8000:80 + networks: + - internal + - external mysql: image: mysql:5.7 environment: MYSQL_ALLOW_EMPTY_PASSWORD: 'yes' + networks: + - internal +networks: + internal: + internal: true + external: + name: api_network
web
version: '3.7' services: web: #XXX APIアクセスはcurlで代用。 image: amazonlinux:2 command: curl api:80 +networks: + default: + external: + name: api_network
入門docker 復習(7)
プロダクションでの活用
オーケストレーションツール
オーケストレーションツールとは
- 複数のDockerを扱うための技術
- 主に以下の機能をもち、本番のワークロードに必要な機能を備えている
- Dockerの管理/自動復旧
- ネットワークの管理
- オートスケール
代表的なオーケストレーションツール
- docker-compose
- Docker社が所管するオーケストレーションツール
- ローカルでDockerを動かす際のデファクトスタンダードなツール
- Docker for Windows/Mac インストール時に同時にインストールされる
- swarm
- docker-composeと同じくDocker社所管ツール
docker-compose.yml
を拡張することで本番のワークロードでDockerを使用できる
- ECS(Elastic Container Service)
- AWSが開発したオーケストレーションツール
- 他のツールより責任範囲が狭いため、学習コストが低い
- Kubernetes
- Google社が開発したオーケストレーションツール
- 現在のデファクトスタンダート
docker-compose
概要
- docker-composeはローカルでDockerのオーケストレーションを行うツール
- DockerのビルドからNetworkやVolumeの管理をコードベースで定義して行う
サンプル
version: '3.7' services: nginx: build: context: . dockerfile: docker/nginx/Dockerfile volumes: - ./public:/var/www/html/public:ro ports: - 8080:80 environment: PHP_HOST: app app: build: context: . dockerfile: Dockerfile env_file: - .env.example # volumes: # - .:/var/www/html:cached mysql: image: mysql:5.7 volumes: - ./mysql:/var/lib/mysql:delegated command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci environment: MYSQL_ALLOW_EMPTY_PASSWORD: 'yes' ports: - 13306:3306
version
- docker-composeのバーション
- こだわりがなければ最新を記述
services
- 起動するコンテナの定義
- ngix,app,mysqlを定義
image
- コンテンを起動するDockerImageを指定
build
- docker buildの実行情報
- この情報をもとにDockrをビルドし、ビルドしたイメージを使用してコンテナを起動する
- imageまたはbuildどちらかを記述
volumes
- ボリュームのマウントを行う
-
- ポートの解放を行う
- 左にホスト、右にコンテナのポートを指定する
environment
- 起動するコンテナへ環境変数を定義する
env_file
- ファイルに記載された環境変数を読み取り、コンテナに定義する
command
- Dockerfileで定義されているCMDの上書きを行う
docker-composeのコマンド
up
- カレントの
docker-compose.yaml
を参照してdocker-composeの起動docker-compose up
- カレントの
down
- カレントの
docker-compose.yaml
に紐づいているContainerとNetworkを削除docker-compose down
- イメージも削除
docker-compose down --rmi all
- カレントの
rm
- Volumeを削除
docker-compose rm
- Volumeを削除
入門docker 復習(6)
プロダクションでの活用
イメージの仕組み
Container
- DockerImageはReadOny
- Docker Containerを作成することで変更可能なレイヤーが生成され、レイヤーの上でプロセスを動かす
docker diff
によりコンテナ起動後に変更されたファイルを確認できる
Unison FileSystem
- Containerレイヤーに操作対象のパスが存在しない場合、Imageレイヤーにファイルが無いか確認する
- Docker ContainerからDocker Imageへファイルを読み込む際は1レイヤーごとに操作するため、オーベーヘッドが大きくなる可能性がある
- dockerのデフォルトのファイルの読み書きはコピーライトオン形式(元データは変更せず、新規更新を新たな場所に書き込みむこと)のため、ファイルの更新頻度が高いログなどはDataVolumeを使用してオーバーヘッドを小さくするべき
Dockerイメージ
- イメージは複数のイメージの積み重ねで出来ている
- 積み重なったイメージを中間イメージと呼ぶ、
docker history <イメージ名>
で確認可能 - RUNコマンドをパイプで繋げることで中間イメージを減らし、軽量化が可能になる
- レイヤーを作成するコマンド(RUN , COPY , ADD )を極力増やさない
Dockerfileのベストプラクティス
軽量なイメージを作る
- イメージはサイズが軽く、レイヤーが少ないものが良い
- サイズが思いpullに時間がかかり、レイヤーが増えるとオーバヘッドが増加する
最小限の構成にする
- 1コンテナ1プロセスにする
- 複数のプロセスを使用する場合は、それぞれのコンテナに分けてオーケストレーションツールによりコンテナを協調させる
軽量なベースイメージを使用する
- Alpine OSという軽量なOSでイメージを作成する
.dockerignoreを使う
- Dockerfileのビルド時に無視するファイルやディレクトリを指定する
.git
のようなコンテナ内に不要な情報、node_modules
のような上書きされると困るものを記載する
Build
キャッシュを意識する
- DockerImageは各コマンド毎にキャッシュを作成する(中間レイヤー)
- ビルド後にファイルに変更があった場合、変更直前のキャッシュからビルドを実行する
Multi-Stage Build
- 複数のDockerImageを作成し、その中から特定のファイルを抽出して1つのDockerImageを作成する
入門docker 復習(5)
プロダクションでの活用
設計
1コンテナ=1プロセス
- Dockerは1プロセスをフォアグラウンドで走らせるため、1コンテナ=1プロセスの粒度で設計する
- ただし、設計上1プロセスが難しい場合は1コンテナにつき1つの関心事にする
永続的なデータはマネージドサービスに任せる
- 永続的なステータスにより依存が発生した場合、Dockerの性能に影響を及ぼす
- ステートを持たない設計をする
セキュリティ
rootユーザーを使わない
- コンテナ内に侵入された時の影響を最小限にするため
- Docer Imageのデフォルトがrootユーザーのため注意が必要
USER
コマンドでユーザーを変更する
野良のDocker Imageをベースイメージにしない
- ユーザー製のイメージは過去に何度もマイニング(処理能力が使われる)や攻撃を受けているため
- ベースイメージは公式のものを使用する
ビルド時に機微情報を与えない
- ビルド時に秘密鍵やパスワードなどを与えない
- どうしても必要な場合は
--secret
や--ssh
オプションを使用してセキュアにビルドする - パスワードや接続情報は環境変数やVault(セキュリティフォルダ)へ格納する
ホストのファイルのマウントの仕方
- ホストのファイルをマウントする際は最小限の権限とパスで範囲を狭くする
- 特にdockerソケットはCIや監視でマウントを要求するソフトが増えてきている
- ソケットをマウントする場合はRead-Onlyでマウントする
.dockerignoreファイルを使う
- Dockerビルド時に無視するパスを記述するファイル
.env
などのDBへの接続情報や.git
やnode_modules
のようなビルドに不要なパスは無視することでビルドが高速かつイメージが軽量になる
デバッグ
- イメージの確認
docker images
ホスト上の全てのコンテナを確認
docker container ls -a
- 実行中のコンテナだけ確認
docker container
コンテナの停止
docker stop <コンテナID>
- 全コンテナの停止
docker stop $(docker ps -q)
コンテナの削除
docker rm <コンテナID>
- 全コンテナの削除
docker rm $(docker ps -q -a)
イメージの削除
docker rmi <イメージID>
- 全イメージの削除
docker rmi $(docker images -q)
コンテナにログインしてbashで操作(起動中のみ)
docker exec -it <コンテナID> bash
コンテナのログを確認
docker logs <コンテナID>
- 起動したプロセスの標準出力と標準エラーのログのため、ファイルに書き込まれるログは確認出来ない
停止したコンテナに入る
- 停止したコンテナから新しいイメージを作成する
docker commit <コンテナID> <新しいコンテナ名>
- 新しいコンテナにログインする
docker run -it exited-container bash
- 停止したコンテナから新しいイメージを作成する