by Marius Lazar

通过马里乌斯·拉扎尔(Marius Lazar)

我们如何使用CircleCI 2.0来构建Angular应用并将其部署到AWS S3 (How we used CircleCI 2.0 to build and deploy an Angular app to AWS S3)

In today’s world, continuous integration and deployment (CI & CD) is a very common practice and an important part in any application life cycle. If you want to avoid spending valuable time on tasks that you can actually automate, keep on reading.

在当今世界,持续集成和部署(CI&CD)是非常常见的做法,并且在任何应用程序生命周期中都是重要的组成部分。 如果您想避免将宝贵的时间花在实际上可以自动化的任务上,请继续阅读。

In this tutorial, I’m going to walk you through the steps we have followed to integrate a CI & CD pipeline in the development process of one of our Angular apps using CircleCI 2.0 and AWS S3.

在本教程中,我将带您逐步完成在使用CircleCI 2.0和AWS S3的Angular应用之一的开发过程中集成CI和CD管道的步骤。

要求 (Requirements)

Before you start this tutorial, I assume you have the following:

在开始本教程之前,我假设您具有以下条件:

  • A CircleCI accountCircleCI帐户
  • An AWS account with rights to create new users有权创建新用户的AWS账户
  • An AWS S3 Bucket一个AWS S3存储桶
  • A Bitbucket or Github repository with your project项目中的Bitbucket或Github存储库
  • A cup of coffee — you know… keeps you warm and focused :)一杯咖啡-您知道……让您保持温暖和专注:)

设置CircleCI (Setting up CircleCI)

Let’s get to work. For setting up CircleCI, you need to create a new folder in your project root called .circleci (notice the dot) and add a config.yml file to it. Leave it empty for a second.

让我们开始工作。 要设置CircleCI,您需要在项目根目录中创建一个名为.circleci (注意点)的新文件夹,并向其中添加config.yml文件。 让它空一秒钟。

Go to the CircleCI interface and add your project by going to Projects tab > Add Project . CircleCI should have already found all your public repos. Select your project and press the Setup project button.

转到CircleCI界面并通过转到“ Projects tab > Add Proj项目”来添加您的项目。 CircleCI应该已经找到了您所有的公共存储库。 选择您的项目,然后按“ he Setup proj项目”按钮。

Select the options that fit you best (Linux/Platform 2.0/Node in our case), copy the sample config generated down on the page into your own config file, and push the changes to your repo. Now you can press the Start building button.

选择最适合您的选项(在我们的例子中为Linux / Platform 2.0 / Node),将页面上向下生成的样本配置复制到您自己的配置文件中,然后将更改推送到您的存储库中。 现在,您可以按Start building按钮。

You can find a gist with the final configuration here.

您可以在此处找到具有最终配置的要点。

了解CircleCI配置文件 (Understanding the CircleCI configuration file)

The bread and butter of this tutorial is to understand how to make use of the CircleCI config file. It has 3 main components: a version, a list of jobs, and a list of workflows.

本教程的基本内容是了解如何利用CircleCI配置文件。 它具有3个主要组件:版本,作业列表和工作流程列表。

The version is pretty obvious. It’s the CircleCI version that we are going to use.

该版本非常明显。 这是我们将要使用的CircleCI版本。

Then we have the list of jobs. You can think of a job like an independent environment for running a list of commands or steps. Common things that you can achieve within a job include:

然后,我们有了工作清单。 您可以将作业视为独立的环境,以运行命令或步骤的列表。 您可以在工作中实现的常见事项包括:

  • Installing the tools you need to run/build/test your project安装运行/构建/测试项目所需的工具
  • Executing bash commands执行bash命令
  • Storing or restoring items from the CircleCI cache从CircleCI缓存中存储或还原项目

Then we have the list of workflows. A workflow is a way to manage your jobs. Let’s say you need a job to run only on specific branches or at specific times, or you want some of the jobs to run in parallel and some in sequence. That’s what workflows are for.

然后,我们获得了工作流程列表。 工作流是管理工作的一种方式。 假设您需要一个作业仅在特定分支或特定时间运行,或者您希望某些作业并行运行,而某些则依次运行。 那就是工作流程的目的。

A basic CircleCI config structure:

CircleCI基本配置结构:

In our case we have two jobs: the build job and the deploy job. I will describe each of them in the following sections, but for now, let’s see what attributes we are going to use for each of the jobs:

在我们的例子中,我们有两个工作: 构建工作部署工作 。 我将在以下各节中对它们中的每一个进行描述,但是现在,让我们看看我们将对每个作业使用哪些属性:

  • The docker attribute — specify a Docker image used to create the container of the environment. CircleCI comes with a list of pre-built images that you can find here

    docker属性-指定用于创建环境容器的Docker映像。 CircleCI带有预建图像列表,您可以在此处找到

  • The working_directory attribute— the current directory which will be the place where all the steps will run

    working_directory属性-当前目录,将在其中运行所有步骤

  • The steps attribute — a list of steps (commands) that you want to run in the current job

    steps属性-您要在当前作业中运行的步骤(命令)的列表

There are a few types of steps that we are going to use in our configuration:

我们将在配置中使用几种类型的步骤:

  • The checkout step — used to checkout the code from the current branch into the working directory

    检出步骤-用于将代码从当前分支检出到工作目录中

  • The run step — used to execute a bash command. You can specify a descriptive name which you are going to see in the CircleCI interface

    运行步骤-用于执行bash命令。 您可以指定一个描述性名称,该名称将在CircleCI界面中显示

  • The save_cache step — used to store a cache of a file or a directory in the CircleCI storage. A common use case is to install the npm dependencies only once and then cache the node_modules folder using a hash of the package.json file as the cache key

    save_cache步骤—用于在CircleCI存储中存储文件或目录的缓存。 一个常见的用例是只安装npm依赖项一次,然后使用package.json文件的哈希作为缓存键来缓存node_modules文件夹

  • The restore_cache step — used to restore a cached item using the cache key

    restore_cache步骤-用于使用缓存键还原缓存的项目

Each job has access to some predefined environment variables. You can check the full list here. You can also set up environment variables from the CircleCI interface or as a job attribute, but in this tutorial we are only going to use the following environment variables:

每个作业都可以访问一些预定义的环境变量。 您可以在此处查看完整列表。 您也可以从CircleCI界面或作为作业属性来设置环境变量,但是在本教程中,我们将仅使用以下环境变量:

  • CIRCLE_BRANCH — represents the current branchCIRCLE_BRANCH —代表当前分支
  • CIRCLE_SHA1 — represents a hash of the current commitCIRCLE_SHA1 —表示当前提交的哈希

配置CI管道 (Configuring the CI pipeline)

The CI pipeline will be responsible for building, linting, and testing the source code. All three processes will be aggregated into a single job called the build job.

CI管道将负责构建,整理和测试源代码。 所有这三个过程将汇总到一个称为构建作业的作业中

You can have a quick look at the final build job below, but I’m going to take each step separately so we can learn a bit more about what’s happening there.

您可以快速浏览下面的最终构建作业,但是我将分别进行每个步骤,以便我们可以了解有关那里发生的事情的更多信息。

  1. We start by checking out the code from the current branch我们首先从当前分支中签出代码
# Checkout the code from the branch into the working_directory- checkout

2. We log the current branch for debugging purposes

2.我们记录当前分支以进行调试

# Log the current branch- run:    name: Show current branch    command: echo ${CIRCLE_BRANCH}

3. We restore the node_modules folder from the cache if it exists. You can have a peak at step 5 to see how it was saved.

3.如果存在,我们将从缓存中还原node_modules文件夹。 您可以在第5步看到一个峰,以了解它是如何保存的。

# Restore local dependencies from cache- restore_cache:    keys:        - v1-dependencies-{{ checksum "package.json" }}        - v1-dependencies-

You notice that we are using two cache keys. A key is a pattern to search for a cached item. The first one is specific to the current package.json file and the second one is more generic and matches all previously cached node_modules folders.

您会注意到我们正在使用两个缓存键。 密钥是用于搜索缓存项目的模式。 第一个特定于当前package.json文件,第二个更通用,并且匹配所有先前缓存的node_modules文件夹。

In case the very specific cache doesn’t exist, we are going to look for any previously cached node_modules folder and restore that instead. This is useful when only some of our dependencies have been updated, because we don’t need to download and install the whole list of dependencies. We are only going to do that for the updated packages and restore the unchanged ones from the cache.

如果不存在非常特定的缓存,我们将查找以前缓存的任何node_modules文件夹,并将其还原。 当仅更新了一些依赖项时,这很有用,因为我们不需要下载并安装整个依赖项列表。 我们只会对更新的软件包执行此操作,并从缓存中还原未更改的软件包。

4. We install the project dependencies. If those dependencies have already been restored from the cache, this step will be very quick. Otherwise it can take up to a few minutes. That’s why caching is important. Saves you time and money.

4.我们安装项目依赖项。 如果这些依赖关系已经从缓存中恢复,则此步骤将非常快。 否则可能需要几分钟。 这就是为什么缓存很重要。 为您节省时间和金钱。

# Install project dependencies- run:    name: Install local dependencies    command: npm install

5. We cache the node_modules folder in case it doesn’t exist. Keep in mind that a cache is immutable, so it will not be overwritten if it already exists.

5.如果不存在node_modules文件夹,我们将对其进行缓存。 请记住,缓存是不可变的,因此如果缓存已经存在,则不会被覆盖

# Cache local dependencies if they don't exist- save_cache:    key: v1-dependencies-{{ checksum "package.json" }}    paths:        - node_modules

A new cache will be generated with the folders/files specified in the paths attribute every time something is changed in the package.json file. The key of the cache is generated using the checksum function, which will output a base64 encoded hash of the package.json file’s content.

每当package.json文件中的内容发生更改时,都会使用paths属性中指定的文件夹/文件生成一个新的缓存。 缓存的密钥使用校验和函数生成,该函数将输出package.json文件内容的base64编码哈希。

One commonly used technique is to prefix your cache key with a version number, so whenever you want to regenerate your caches, you can just change the version number.

一种常用的技术是在缓存密钥之前添加版本号,因此,每当您要重新生成缓存时,都可以更改版本号。

6. We run the lint and test commands. It’s probably worth noticing that if any of the steps fail, the whole build will fail.

6.我们运行lint和测试命令。 可能值得注意的是,如果任何步骤失败,整个构建都会失败。

# Lint the source code- run:    name: Linting    command: npm run lint
# Test the source code- run:    name: Testing    command: npm run test

7. We run the build command. Notice that we are going to use a multi-line command with each line running in the same shell, so we start the command with the pipe (|) character.

7.我们运行build命令。 注意,我们将使用多行命令,并且每行都在同一shell中运行,因此我们以竖线(|)字符启动该命令。

We check the current branch name and run the corresponding npm script to build the project. We do this because we have different configurations based on the environment. The resulting files will be saved into the dist folder.

我们检查当前分支名称,并运行相应的npm脚本来构建项目。 我们这样做是因为我们根据环境有不同的配置。 生成的文件将保存到dist文件夹中。

# Build project with different configuration based on# the current branch- run:    name: Building    command: |        if [ "${CIRCLE_BRANCH}" == "staging" ]; then            npm run build-qa        elif [ "${CIRCLE_BRANCH}" == "master" ]; then            npm run build-prod        else            npm run build-dev        fi

8. Finally, we save the dist folder into the cache so we can restore it later in the deploy job. We are using both CIRCLE_BRANCH and CIRCLE_SHA1 environment variables to generate a unique cache key which doesn’t already exists in the cache.

8.最后,我们将dist文件夹保存到缓存中,以便稍后可以在部署作业中将其还原。 我们同时使用CIRCLE_BRANCHCIRCLE_SHA1环境变量来生成唯一的缓存键,该键在缓存中尚不存在。

Notice that we are not in a shell command, so we need to take those variables from the .Environment variable.

注意,我们不在shell命令中,因此我们需要从.Environment变量中获取这些变量。

# Cache the dist folder for the deploy job- save_cache:    key: v1-dist-{{ .Environment.CIRCLE_BRANCH }}-{{ .Environment.CIRCLE_SHA1 }}    paths:        - dist

As a side note, we first tried installing angular-cli globally and cached it for later use, but it would take up to 30s to finish the installation even when it was cached. So we decided to create a few npm scripts to run ng commands using the local angular-cli.

附带说明一下,我们首先尝试在全局范围内安装angular-cli并将其缓存以备后用,但是即使已缓存,它也可能需要30秒钟才能完成安装。 因此,我们决定创建一些npm脚本来使用本地angular-cli运行ng命令。

"scripts": {  "ng": "ng",  "start": "ng serve --env=local",  "build": "ng build",  "test": "ng test",  "lint": "ng lint",  "e2e": "ng e2e",  "build-dev": "ng build --target=development --environment=dev",  "build-qa": "ng build --target=production --environment=qa",  "build-prod": "ng build --prod"}

And that’s it! We now have a working CI pipeline. You should be able to save this into your own config file, push it to your repo, and check if everything is working as you expect.

就是这样! 现在,我们有一条有效的CI管道。 您应该能够将其保存到自己的配置文件中,将其推送到您的仓库中,并检查一切是否按预期工作。

In case you are wondering, you don’t need any workflow in place to run a job. By default, each job will fire when you push a change.

如果您想知道,则不需要任何工作流程即可运行作业。 默认情况下,当您推送更改时,每个作业都会触发。

配置CD管道 (Configuring the CD pipeline)

The CD pipeline will be responsible for deploying the distribution files resulting from the build job to an AWS S3 bucket. Guess what? We are going to call this the deploy job.

CD管道将负责将构建作业产生的分发文件部署到AWS S3存储桶。 你猜怎么了? 我们将其称为部署工作

Before we can continue, we have to give CircleCI permissions to access the AWS S3 Bucket.

在继续之前,我们必须授予CircleCI权限以访问AWS S3存储桶。

First, we are going to create a new IAM user in the AWS Management Console. Go to Services > IAM > Users > Add User . Give it a name and select the Programmatic access box for the Access type.

首先,我们将在AWS管理控制台中创建一个新的IAM用户。 转到Services > IAM > Users >添加用户。 给它起一个名字,并为“访问”类型选择“程序访问”框。

Go Next . We now have to go give the user some permissions. In our case, we only need the circleci user to be able to Read/Write an AWS S3 Bucket. Find and select the AmazonS3FullAccess policy, then press theCreate user button.

转到Next 。 现在,我们必须给用户一些权限。 在我们的情况下,我们仅需要circleci用户即可读取/写入AWS S3存储桶。 查找并选择AmazonS3FullAccess策略,然后按Create user按钮。

On the next page, you will have an Access key ID and a Secret access key for the new user. Keep this page open and go to the CircleCI interface. Get into the project settings and search for AWS Permissions. You will need to use the previously generated keys in here.

在下一页上,您将为新用户提供一个访问密钥ID和一个秘密访问密钥 。 保持此页面打开并转到CircleCI界面。 进入项目设置并搜索AWS Permissions 。 您将需要在此处使用先前生成的密钥。

Once you’ve done that, we can continue with our deploy job.

完成此操作后,我们可以继续进行部署工作。

Same as previously, you have the final deploy job below. But I’m going to discuss each step separately, even though they are pretty straight-forward this time.

与之前相同,您将在下面完成最终的部署工作。 但是我将分别讨论每个步骤,即使这次它们很简单。

  1. We start by logging the branch name for debugging purposes.我们首先记录分支名称以进行调试。
# Log the current branch- run:    name: Show current branch    command: echo ${CIRCLE_BRANCH}

2. We restore the cached dist folder saved on the build job.

2.我们还原保存在构建作业中的缓存的dist文件夹。

# Restore cache from the build job which contains the# dist folder that needs to be deployed- restore_cache:    key: v1-dist-{{ .Environment.CIRCLE_BRANCH }}-{{ .Environment.CIRCLE_SHA1 }}

3. We install the aws cli using sudo rights.

3.我们使用sudo权限安装aws cli。

# Install AWS cli- run:    name: Install aws cli    command:        sudo apt-get -y -qq install awscli

4. We run the deploy command which is going to deploy the code from the dist folder to the AWS S3 Bucket corresponding to the current environment. We have again a multi-line command, so we need to start with the pipe (|) character.

4.我们运行deploy命令,该命令会将dist文件夹中的代码部署到与当前环境相对应的AWS S3存储桶。 我们再次有一个多行命令,因此我们需要以竖线(|)开头。

# Deploy to the S3 bucket corresponding to the current branch- run:    name: Deploy to S3    command: |        if [ "${CIRCLE_BRANCH}" == "develop" ]; then            aws s3 sync dist s3://project-dev/ --delete        elif [ "${CIRCLE_BRANCH}" == "staging" ]; then            aws s3 sync dist s3://project-qa/ --delete        elif [ "${CIRCLE_BRANCH}" == "master" ]; then            aws s3 sync dist s3://project/ --delete        fi

The signature for deploying to an AWS S3 Bucket using the aws cli is as follows:

使用aws cli部署到AWS S3存储桶的签名如下:

aws s3 sync <% path-to-folder %> s3://<% bucket-name %>/ --delete

The delete flag will clear the bucket before deploying any files.

删除标志将在部署任何文件之前清除存储桶。

One more thing. Or maybe two… We have encountered 2 errors after we had this configuration in place. Maybe they are not applicable in your case, but I will still give you a short summary.

还有一件事。 也许是两个……适当配置此配置后,我们遇到了2个错误。 也许它们不适用于您的情况,但是我还是给您一个简短的摘要。

  1. The region of the S3 Bucket was not specified.未指定S3存储桶的区域。

A client error (PermanentRedirect) occurred when calling the ListObjects operation: The bucket you are attempting to access must be addressed using the specified endpoint. Please send all future requests to this endpoint.

调用ListObjects操作时发生客户端错误(PermanentRedirect):尝试访问的存储桶必须使用指定的端点进行寻址。 请将所有将来的请求发送到此端点。

To solve this error, we had to add the bucket region to the deploy command:

要解决此错误,我们必须将bucket区域添加到deploy命令:

aws --region eu-west-2 s3 sync <% path %> s3://<% bucket-name %>/

2. The authorization to the S3 Bucket was using an old protocol which is not supported by the current bucket.

2.对S3存储桶的授权使用的是旧协议,当前存储桶不支持该协议。

A client error (InvalidRequest) occurred when calling the ListObjects operation: The authorization mechanism you have provided is not supported. Please use AWS4-HMAC-SHA256.

调用ListObjects操作时发生客户端错误(InvalidRequest):不支持您提供的授权机制。 请使用AWS4-HMAC-SHA256。

To solve this error, we had to set the authorization mechanism for authenticating an AWS S3 Request to use the Signature Version 4 before running the deploy step:

为了解决此错误,我们必须在运行部署步骤之前设置用于对使用签名版本4的AWS S3请求进行身份验证的授权机制:

# Set the signature version for the S3 auth- run:    name: Setting Signature Version 4 for S3 Request Authentication    command: aws configure set default.s3.signature_version s3v4

That’s it! We now have a working CD pipeline. Only one small problem… It will run on every push. So let’s configure a workflow to solve this.

而已! 现在,我们有一个正在运行的CD管道。 只有一个小问题…它会在每次推送时运行。 因此,让我们配置一个工作流程来解决此问题。

将CI和CD作业放入工作流程 (Putting the CI & CD jobs into a workflow)

In our case, we want to run the build job on every commit and the deploy job only when we commit to develop, staging, or the master branch. A workflow, by default, is triggered by pushing to any branch.

在我们的例子中,我们只希望在提交开发,暂存或master分支时才在每次提交和部署作业上运行构建作业。 默认情况下,工作流程是通过推送到任何分支来触发的。

We actually wanted the build job to run only when we make a Pull Request (PR), and this is possible by going into the Advance Settings of your CircleCI project and turning on the Only build pull requests option.

实际上,我们实际上希望构建作业仅在发出“拉取请求”(PR)时运行,这可以通过进入CircleCI项目的“高级设置”并打开“ Only build pull requests 选项。

But the problem comes when you need to run the workflow on PR and also on develop, staging, and master branches. We couldn’t find how to make this work. But if you have any suggestions, please leave me a comment!

但是问题出在需要在PR以及开发,登台和主分支上运行工作流时。 我们找不到如何使这项工作。 但是,如果您有任何建议,请给我评论!

Back to our workflow config. It is pretty self-explanatory:

返回我们的工作流程配置。 这是不言自明的:

You can see that we have defined the build_and_deploy workflow which contains… the build and deploy jobs. The build job has no restrictions, so it will run whenever the workflow runs.

您可以看到我们已经定义了build_and_deploy工作流,其中包含……构建和部署作业。 构建作业没有任何限制,因此它将在工作流程运行时运行。

On the other hand, the deploy job has a require property for the build job which means that it will only run if the build job is successful. It also has a filter attribute which is used to select the branches that it will run on.

另一方面,部署作业具有构建作业的require属性,这意味着它将仅在构建作业成功时运行。 它还具有一个filter属性,该属性用于选择将在其上运行的分支。

With this configuration in place, we have limited the execution of the deploy job to the develop, staging, and master branches only when the build job is successful, which is exactly what we wanted.

有了此配置,仅当构建作业成功时,我们才将部署作业的执行限制在开发,登台和主分支上,这正是我们想要的。

That’s pretty much it. A gist with the entire configuration can be found here.

就是这样。 完整配置的要点可以在这里找到。

奖励功能 (Bonus feature)

If you are like us and you would like know what’s happening with your project, you will be glad to hear that there is a CircleCI app for Slack which can be configure to give you real time alerts when a build succeeds or fails. It’s nice to have.

如果您像我们一样,并且想知道项目的进展,您将很高兴听到有一个用于Slack的CircleCI应用程序,可以将其配置为在构建成功或失败时向您发出实时警报。 真高兴。

最后的想法 (Final thoughts)

I know it can be intimidating, but don’t be afraid to integrate a CI & CD pipeline into your project. It will take a bit of time until you get the configuration right, but it’s worth it!

我知道这可能令人生畏,但不要害怕将CI和CD管道集成到您的项目中。 正确配置之前需要花费一些时间,但这是值得的!

If you think this article was helpful for you, please recommend and share!

如果您认为本文对您有所帮助,请推荐并分享!

Thanks for reading! If you have any comments or questions, please reach out to me! I’m always glad to help :)

谢谢阅读! 如果您有任何意见或疑问,请与我联系! 我总是很乐意为您提供帮助:)

翻译自: https://www.freecodecamp.org/news/our-journey-for-using-circleci-2-0-to-build-and-deploy-an-angular-app-to-aws-s3-8e7ea3f51503/

我们如何使用CircleCI 2.0来构建Angular应用并将其部署到AWS S3相关推荐

  1. 串行测试 并行测试_如何通过CircleCI测试并行性增加构建时间

    串行测试 并行测试 by Karel Rochelt 卡雷尔·罗切尔特(Karel Rochelt) 如何通过CircleCI测试并行性增加构建时间 (How to boost build time ...

  2. [面试专题]Vue.js 2.0 独立构建和运行时构建的区别

    Vue.js 2.0 独立构建和运行时构建的区别 标签(空格分隔): 未分类 在使用 Vue.js 2.0 时,有独立构建(standalone)和运行时构建(runtime-only)两种版本可供选 ...

  3. SpringBoot3.0 Native构建

    SpringBoot3.0支持了将java程序构建为可执行文件 其实将java构建为native应用,不是第一次提及了,我第一次听到这个想法的时候是Quarkus(exe4j不算哈,本质上还是启动了j ...

  4. 基于qemu-riscv从0开始构建嵌入式linux系统ch10. qemu之virtio与fw_cfg

    基于qemu-riscv从0开始构建嵌入式linux系统ch10. qemu之virtio与fw_cfg 上一节我们已经基本完成了uboot的移植,下一步自然就是移植linux kernel.在真实的 ...

  5. 2020云智中国-百度智能云尤莉:智能视频云2.0,构建泛视频“新基建”

    2020云智中国西安站论坛于12月11日,在西安香格里拉大酒店顺利举办.论坛主旨为百度智能云推动产业智能化再升级.百度智能云尤莉在论坛上发表了主题演讲:智能视频云2.0,构建泛视频"新基建& ...

  6. 基于qemu-riscv从0开始构建嵌入式linux系统ch3. 添加中断控制器、串口、pflash支持

    基于qemu-riscv从0开始构建嵌入式linux系统ch3. 添加中断控制器.串口.pflash支持 添加串口支持 真实板卡的初期调试中,串口打印可谓神器,几乎所有的SOC都会带有串口这个外设,因 ...

  7. Spring Boot中使用Swagger3.0.0版本构建RESTful APIs

    文章目录 一.项目描述 二.简介 三.Swagger2.X和Swagger3.0.0 的对比 1)SpringFox 2.x 发布 2)SpringFox 3.0.0 发布 3)swagger3.0 ...

  8. k8s aws 部署_如何在短短30分钟内使用CircleCI设置到AWS S3的持续部署

    k8s aws 部署 by Adam Watt 通过亚当·瓦特 如何在短短30分钟内使用CircleCI设置到AWS S3的持续部署 (How to setup Continuous Deployme ...

  9. angular 模块构建_如何通过11个简单的步骤从头开始构建Angular 8应用

    angular 模块构建 Angular is one of the three most popular frameworks for front-end development, alongsid ...

最新文章

  1. Xamarin SQLite教程Xamarin.iOS项目添加引用
  2. HTML5API(5)
  3. NOSQL的Redis的基础
  4. Struts2-获取值栈对象与结构
  5. 3.关于QT中的MainWindow窗口,MenuBar,ToolBar,QuickTip等方面的知识点
  6. CL_BSP_WD_VIEW_MANAGER-MANIPULATE_RESPONSE
  7. 使用Spring Integration进行消息处理
  8. ios 点生成线路 百度地图_iOS SDK | 百度地图API SDK
  9. 简析银行业数据中心的特点
  10. android 用LruCache读取大图片并缓存(转)
  11. oracle12c bug,12c expdp ORA-31623 -又遇到BUG
  12. R语言---ggplot图片边缘空白设置和ggplot映射的shape值多余6个
  13. vbs教程(1):弹窗
  14. linux每个进程有4g,32位Linux单进程有4G内存限制
  15. 2022年山东大学游戏策划考试回忆版
  16. 电脑锁屏卡死以及任务栏卡死的解决办法
  17. TS在vue中的应用
  18. Vulnhub-theEther
  19. Excel如何从混合数据中提取出手机号码
  20. 1011 A+B 和 C (15分)(输出格式 数据类型范围)

热门文章

  1. c语言中如何取消最后一个空格,新人提问:如何将输出时每行最后一个空格删除...
  2. Ubuntu中NS2安装详细教程
  3. 洛谷 P4012 深海机器人问题【费用流】
  4. Jquery的ajax提交成功后刷新页面
  5. css样式中如何设置中文字体?
  6. HDU4911 Inversion 解题报告
  7. ASP.NET N问N答 (一) ASP.NET怎么导出到WORD?(把girdview里面的数据到出到word)
  8. (转微软网站)如何安装 Microsoft Dynamics CRM 4.0 具有最低必需权限
  9. Visual Editor插件下载、安装问题(Eclipse3.1.1)
  10. docker linux k8s kubeadm