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_testfeatureの部分が一致してしまい、pushが出来なかった

(同ディレクトリの中に同名フォルダが作れないようなイメージ)

対応

  • 不要なリモート追跡ブランチを削除し、pushする
    1. git remote prune orignでリモートブランチを削除する
    2. 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

  • オーバヘッドの少なさ、スケールアウトのしやすさから世界中のプロダクションで利用されている
  • クラウドプラットフォーム(AWS,GCP)でもコンテナを運用するツールが整備されている

新しい開発スタイルへ

  • Dockerの普及でインフラがコードレベルで簡単に修正できるようになった
  • インフラエンジニアとサーバーサイドエンジニアの垣根がなくなりつつある
  • 現代的な開発のためにフロントエンドやスマホアプリエンジニアにも必要な技術になりつつある

入門docker 復習(8)

プロダクションでの活用

プロダクションへの導入

  1. ローカル環境のDocker化

    • チームの開発環境を統一する
  2. テスト/CIへの導入

  3. ステージングへの導入
    • 本番前に動作確認する
  4. 本番への導入

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のネットワークを用意する
    • internalはリポジトリ内の内部的な通信ネットワーク(MySQLのようにデータストアを不用意に用意しないために使用)
    • 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-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

    • ボリュームのマウントを行う
  • ports

    • ポートの解放を行う
    • 左にホスト、右にコンテナのポートを指定する
  • 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

入門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への接続情報や.gitnode_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