どのようにGitlabのCI/CDと展開を自動化する展開


アプリケーションの開発はプログラミングそのもので終わりません.その完了後、ユーザーがそれを使用できるように、サーバーにアップロードする必要があります.これは多くの点で可能です.手動または自動.このポストでは、サーバーに自動的にアプリケーションと新しい機能をアップロードする方法を示します.私はこのプロセスのためにgitlab ci/cdを使います.そして、それは単位テストを実行して、それから、配備を使っているホストにコードをアップロードします.

なぜ展開するのか?


Deployerは、アプリケーションをサーバーに配備できるシンプルなツールです.それは我々がそれなしで手動で行う必要があります全体のプロセスを自動化します.誰も手動で繰り返し活動をしたい.展開のおかげで、我々は独自のタスクを作成し、選択した順序で実行できます.ツールはすでに組み込まれているpresets symfony、laravel、ワードプレスなど多くのフレームワークのために.展開の疑いのない利点は、何かが間違っている場合には、以前のバージョンにコードをロールバックすることができます.また、多くの展開環境を設定する機能もありますので、コードを生成する前に、テスト環境にアップロードできます.QAチームは新しい機能をテストすることができます.
このツールでは、2つの方法でコードを展開できます.最初は、アプリケーションが実行されるサーバー上のビルドプロセス全体を実行することです.別の方法は、アプリケーションを一度(ローカルまたはCI/CDに)ビルドし、サーバー上の選択した場所にアプリケーションをアップロードすることです.このポストでは、両方のアプローチを示します.

準備準備


ために我々のホスティングにアプリケーションをアップロードするには、展開はそれにアクセスする必要があります.ホスティングへの接続は、SSH経由で鍵認証を行います.マイホスティングでこのような認証を有効にするには、ssh-keygen そして、公開鍵を~/.ssh/authorized_keys ファイル.我々は、それがホスティングに接続することができるように、展開キーに秘密キーを渡します.
さらに、上記のように、配備者は我々のホスト上の倉庫からコードをダウンロードします.したがって、リポジトリやその他の依存関係をホストにアクセスする必要があります.これを行うには、適切な秘密鍵を~/.ssh ディレクトリ.この手順は、ターゲットサーバーにアプリケーションを構築する場合にのみ必要です.
最後に、作成したファイルに適切なパーミッションを与える必要があります.
  • chmod 700 ~/.ssh
  • chmod 600 ~/.ssh/*
  • 展開設定


    インストール


    配備するには、コマンドを実行しますcomposer require deployer/deployer --dev これはベンダーディレクトリに追加されます.
    次に、展開を作成します.アプリケーションのルートディレクトリのPHPファイル.手動で実行するか、次のコマンドを実行します.vendor/bin/dep init .

    構成


    前に述べたように、配備はアプリケーションを配備するための組み込みのプリセットを提供します.この場合、シンフォニー4プリセットを使用しました.その中には、そのような部分がある.
    desc('Deploy project');
    task('deploy', [
        'deploy:info',
        'deploy:prepare',
        'deploy:lock',
        'deploy:release',
        'deploy:update_code',
        'deploy:shared',
        'deploy:vendors',
        'deploy:writable',
        'deploy:cache:clear',
        'deploy:cache:warmup',
        'deploy:symlink',
        'deploy:unlock',
        'cleanup',
    ]);
    
    ここでは、実行した後に実行されるステップを見ることができますvendor/bin/dep deploy コマンド.彼らはすでに実装されていますが、何もあなたがそれらを上書きするか、自分自身を追加することを防ぎます.全体をオーバーライドすることもできますdeploy 引数の手順の異なるリストを持つコマンド.
    以下、ペーストしますdeploy.php アプリケーション用に構成されたファイルです.コメントでは、個々の要素が何であるかを述べました.
    <?php
    namespace Deployer;
    
    // Usage of built-in recipe
    require 'recipe/symfony4.php';
    
    // Here we set the name of the directory in which the particular releases will be located
    set('application', 'myapp');
    
    // Repository address from which the application will be downloaded
    set('repository', '[email protected]:xyz/app.git');
    
    // Set the options with which the `composer install` command should be invoked
    set('composer_options', '{{composer_action}} --prefer-dist --no-progress --no-interaction --no-dev --optimize-autoloader');
    
    // Set how many releases should be kept by Deployer on the server.
    // 3 means that we can go 3 releases back. -1 keeps all releases
    set('keep_releases', 3);
    
    // Specify which files are to be shared between the releases.
    // In my case, it will only be a file with environment variables
    add('shared_files', ['.env']);
    
    // List which directories are to be shared between releases.
    // In my case, it will only be a log directory
    add('shared_dirs', ['var/log']);
    
    // List of directories which must have write permission on the web server.
    add('writable_dirs', ['var/log', 'var/cache']);
    
    set('writable_mode', 'chown'); // we can choose from: chmod, chown, chgrp or acl.
    
    // Web server user
    set('http_user', 'xyz');
    
    // Default stage. If no parameter is specified after calling the `dep deploy` command,
    // the code will be deployed into the stage defined here
    set('default_stage', 'prod');
    
    set('ssh_multiplexing', true);
    
    // Configure the server to which the code will be deployed.
    // Provide here the parameters related to access, i.e. address, user or key path.
    // Additionally, we choose which git branch will be deployed and provide the directory where the application will appear.
    // We can define multiple such hosts in this file, e.g. additional one as a test environment
    host(getenv('HOSTING_HOST'))
        ->stage('prod')
        ->user(getenv('HOSTING_USER'))
        ->port(getenv('HOSTING_PORT'))
        ->identityFile(getenv('HOSTING_SSH_KEY_PATH'))
        ->addSshOption('StrictHostKeyChecking', 'no')
        ->set('branch', 'master')
        ->set('deploy_path', '/home/xyz/domains/xyz.pl/{{application}}')
        ->forwardAgent()
    ;
    
    // Set the path to the PHP version used by our application
    set('bin/php', function () {
    //   return locateBinaryPath('php7.4');
        return '/usr/local/bin/php74';
    });
    
    // I have overwritten the database migration command from the preset
    task('database:migrate', function () {
        $options = '{{console_options}} --allow-no-migration --all-or-nothing --no-interaction';
        run(sprintf('{{bin/php}} {{bin/console}} doctrine:migrations:migrate %s', $options));
    })->desc('Migrate database');
    
    // In my case, to make the application available under the selected domain, the index.php file should be placed in the directory `/home/xyz/domains/xyz.pl/public_html`.
    // The current version can be found in `/home/xyz/domains/xyz.pl/myapp/current/`
    // Therefore, after a successful deployment, I create a symlink to the files in the deployment's public directory
    task('deploy:symlink', function () {
        run( "ln -nfs {{deploy_path}}/current/public/* {{deploy_path}}/../public_html" );
    });
    
    // After the cache is warmed up, I perform a database migration
    after('deploy:cache:warmup', 'database:migrate');
    
    after('deploy:failed', 'deploy:unlock');
    
    上記の構成は、コマンドラインから手動でサーバーにアプリケーションをアップロードするのに十分です.唯一のことは、コールすることですvendor/bin/dep deploy コマンドは、アプリケーションのユーザーにしばらくの間利用可能になります.

    故障処理


    時々、変更がサーバーにアップロードされてエラーが発生し、アプリケーションが正常に動作していない場合があります.
    コマンドを使用して、以前のバージョンにコードを戻すことができます.
    php vendor/bin/dep rollback prod
    
    その後、プロシージャはシンボリックリンクを前のバージョンに戻し、アプリケーションは前のコードで再度起動します.

    Gitlab CI / CDの設定


    最新のアプリケーションでは、展開の全プロセスが通常自動化されます.新しいバージョンのリリース前に、通常、コードやテストの静的解析を実行します.またはJavaScriptとCSSファイルをビルドします.少し時間がかかる.では、さらに一歩進んで、GITLAB環境を使用して、全体のプロセスが行われるようにしましょう.

    実施計画


    gitlabがci/cd環境を実行するために.gitlab-ci.yml ファイルをアプリケーションに追加する必要があります.コードを展開するために実行する手順が含まれます.この場合、プロセスを3つの段階に分割します.
  • dev依存関係を持つアプリケーションの構築- phpUnitとdeployerをrequire-dev セクション.
  • このように構築されたアプリケーションでテストを実行します.
  • すべてがうまくいくなら、我々は配備スクリプトを走らせます.そして、それはサーバーにコードをアップロードして、そこにそれを構築します.
    下記の構成で見ることができるように、最初の2つのステップは我々の倉庫のすべてのブランチで実行されます.三つ目はマスターブランチに対してのみ起動されます.
  • variables:
      COMPOSER_ALLOW_SUPERUSER: 1
      COMPOSER_DEFAULT_OPTIONS: '--optimize-autoloader --classmap-authoritative --no-progress --no-suggest --prefer-dist'
      DOCKER_IMAGE_PHP: 'registry.gitlab.com/xyz/app/php7.4:latest'
    
    stages:
      - build
      - test
      - deploy
    
    build:
      stage: build
      image: ${DOCKER_IMAGE_PHP}
      script:
        - composer install ${COMPOSER_DEFAULT_OPTIONS}
      variables:
        APP_ENV: prod
      artifacts:
        paths:
          - vendor/
          - bin/
    
    phpunit:
      stage: test
      image: ${DOCKER_IMAGE_PHP}
      script:
        - php vendor/bin/phpunit
      variables:
        APP_ENV: test
      dependencies:
        - build
    
    deploy_prod:
      stage: deploy
      image: ${DOCKER_IMAGE_PHP}
      script:
        - mkdir ~/.ssh
        # Private key to access hosting
        - echo "${PRIVATE_KEY}" > ~/.ssh/id_rsa
        - chmod 700 ~/.ssh
        - chmod 600 ~/.ssh/id_rsa
        # We put a specific commit - then in case of any errors in the application, we can redeploy the previous version
        - php vendor/bin/dep deploy prod --revision="${CI_COMMIT_SHA}" 
      only:
        # Branch on which this step will be performed
        - master
      dependencies:
        - build
      # Deploy can be launched automatically when the entire pipeline passes without errors, or manually
      when: on_success
    

    環境変数


    いくつかの環境変数が.gitlab-ci.yml 例えば、DockerClarkImageHow PHPなどのファイルです.他のものは、PrivateRennキーなどではありません.
    私たちはこのファイルに秘密の情報を入れません.なぜなら誰もがそれにアクセスできるからです.セクションでgitlabに追加しますSettings -> CI/CD -> Variables . そこでは、許可されたユーザーだけに利用可能です.

    ドッカーイメージ


    各ステップでは、ドッキング画像を使用する.これはすべてのコードが実行される場所です-リポジトリからコードをダウンロードし、依存関係をダウンロードし、テストし、展開します.したがって、これらの活動に必要なプログラムを含まなければなりません.この場合、次のようになります.
    FROM php:7.4-fpm-buster
    
    RUN apt-get -y update && apt-get -y --no-install-recommends install \
        git \
        zip \
        unzip \
        wget \
        openssl \
        curl \
        openssh-client \
        rsync
    
    COPY --from=composer /usr/bin/composer /usr/bin/composer
    
    そのようなイメージをビルドして、Gitlabコンテナレジストリに置く必要があります.これは次の3つの手順に従います.
    docker login registry.gitlab.com
    docker build -t registry.gitlab.com/xyz/app/php7.4 .
    docker push registry.gitlab.com/xyz/app/php7.4
    

    のアプリケーションのビルド


    私たちがエンドサーバ上でアプリケーションを構築したくないかもしれない場合、代わりにgitlabランナーでそれをします.これは
  • 我々は、複数のサーバーを持っているし、アプリケーションを構築するたびに、各サーバー上で行うよりも高速です
  • 我々は、アプリケーションが正確に同じように見える各サーバーに
  • 我々は、ターゲットサーバー上のNPMや糸のような必要なツールの不足のために資産を構築することはできません
  • 我々は1つの場所に資格情報を維持したい
  • 展開とgitlab私たちはそのような方法でアプリケーションを構築することができます.前のコードに小さな変更を加える必要があります.

    調整装置


    アプリケーションをgitlab ci/cdでビルドするのを可能にするために、私たちはビットを変更する必要がありますdeploy.php ファイル.
    まず第一に、我々はbuild タスク.コードを準備するために、配備者に教えます.build ディレクトリ-リポジトリをダウンロードし、依存関係をインストールします.
    つのファイルを送るので、それはまた、すべてのファイルをアーカイブします.すべてのそれらの事はgitlabランナーで行われます.
    第二にupload タスクは、準備されたリリースをアップロードする必要がありますどこに展開を教えてください.また、ターゲットサーバー上のコードをアンアーカイブします.
    task('build', function () {
        set('deploy_path', __DIR__ . '/.build');
        invoke('deploy:prepare');
        invoke('deploy:release');
        invoke('deploy:update_code');
        invoke('deploy:vendors');
    
        cd('{{deploy_path}}/releases/1/');
        run('rm -rfd deploy.php tests docker');
        cd('{{deploy_path}}');
        run("tar -cvf release.tar.gz -C {{deploy_path}}/releases/1/ $(find {{deploy_path}}/releases/1/ -maxdepth 1 -printf '%P ')");
    })->local();
    
    task('upload', function () {
        upload(__DIR__ . "/.build/release.tar.gz", '{{release_path}}');
        cd('{{release_path}}');
        run('tar -xf release.tar.gz');
        run('rm release.tar.gz');
    });
    
    task('release', [
        'deploy:info',
        'deploy:prepare',
        'deploy:release',
        'upload',
        'deploy:shared',
        'deploy:writable',
        'deploy:cache:clear',
        'deploy:cache:warmup',
        'deploy:symlink',
    ]);
    
    task('deploy', [
        'build',
        'release',
        'cleanup',
        'success'
    ]);
    

    設定ファイルの調整


    中で.GITLAB .YMLファイルは、変更はむしろ化粧品です.我々がそこに加える唯一のものは、ランナーがそれへのアクセスをするように、我々の倉庫への秘密鍵です.
    The deploy_prod パートは次のようになります.
    deploy_prod:
      stage: deploy
      image: ${DOCKER_IMAGE_PHP}
      before_script:  
        - mkdir -p ~/.ssh
        - chmod 700 ~/.ssh
        # Private key to access repository
        - echo "$GITLAB_PRIVATE_KEY" > ~/.ssh/id_rsa
        # Private key to access hosting
        - echo "$HOSTING_PRIVATE_KEY" > ~/.ssh/id_hosting
        - ssh-keyscan gitlab.com >> ~/.ssh/known_hosts
        - chmod 600 ~/.ssh/*
      script:
        - php vendor/bin/dep deploy prod --revision="${CI_COMMIT_SHA}" 
      only:
        - master
      dependencies:
        - build
      when: on_success
    

    変更の展開


    では、master ブランチ、ランナーが起動され、アプリケーションが自動的に我々のホスティングに展開されます.全体のプロセスをgitlabで表示することができますCI/CD -> Pipelines タブ.次のようになります.

    我々のホスティングで、ディレクトリに/home/xyz/domains/xyz.pl/myapp 特定のリリースを見ることができます.

    配備を変更するreleases/[release number] ディレクトリ.我々がそれをセットしたのでdeploy.php ファイルがあります.
    The current ディレクトリは、最後のリリースへのシンボリックリンクです.
    shared ディレクトリは、個々のリリースの間で共有されるファイルです.

    概要


    展開は、アプリケーションの高速自動展開を有効にするシンプルなツールです.それは構成するのが簡単で、我々が使うことができるビルトインセッティングを含みます.GitLabに関連して、それは多くの時間を節約するアプリケーションをアップロードするの全プロセスを自動化することができます.