# Question
Title: What are your companies policies for S3 data durability?
AWS says that their systems are designed for 99.999999999% durability, but apparently there is no guarantees in their SLA.

Yes, this can (hypothetically) be improved by using cross-region replication, but this comes at the cost of paying twice for storage, and also for data transfer costs.

How are your companies handling this? Do they go with pure trust in AWS, or do they spend (a lot) of money to (try to) improve this?

# Answer
> 3 votes
The durability design objective is not especially relevant above some number of 9's, because it is *simultaneously* both extremely unlikely *and* non-zero.

The 99.999999999% durability is easily calculated by reading between the lines as the product of the failure probabilities of 6 copies each with an AFR between 1% and 2%. Older versions of the documentation suggested 3 AZs × 2 devices per AZ was relevant to the durability calculation. Assuming these "devices" were RAID arrays, these AFRs are well within reason.

This is raw durability. It does not take into account natural disasters or acts of war or terrorism or other sabotage (any of which would need to wipe out multiple availability zones within a region) or serious bugs in the S3 system code... all of which are also extremely unlikely but similarly difficult to quantify.

And we need to factor in bugs and human errors in *your* code and systems, compromise of your credentials, and malicious insiders in your organization.

The bottom line is that the risk of loss is extremely low, difficult to quantify, but still non-zero.

I have many millions of objects (dozens of terabytes) in S3 and have never lost one. A majority of them have been stored with copies of both their md5 and sha256 checksums, they are all cataloged in an external database, and extensive audits have never revealed a corrupt or missing object.

But if I lose one critical object in the future, all of that still becomes irrelevant.

**Can you live with the loss of an object? If so, no problem. It's really unlikely that you will lose one.**

But if the data is critical, there is a compelling argument that it should still be backed up, and not exist in only "one place." An object in an S3 bucket is *physically* in multiple places but *logically* that is still "one place" because whether the object exists without corruption ultimately resolves to a single true or false answer from your perspective.

Just as using most classes of RAID arrays reduce the likelihood of data loss but do not remove the need for backup, I would argue that S3's durability -- as high as it is -- does not elminate the requirement that *critical* data be backed up elsewhere.

Cross-region replication is one option, and apparently one important motivation for the introduction of the 1-Zone-Infrequent-Access storage class -- similarly durable except for the case where the availability zone is lost -- was as a very low cost *target* for cross-region replication. It seems to meet that objective -- it's more vulnerable to the loss of a single AZ (and you don't get to pick which AZ) but that's only relevant when data loss has occurred in another bucket, in a totally different region. A replicated bucket could also migrate its copies of objects to Glacier, further reducing long-term storage costs. (Note that very small objects may encounter storage cost *increases* since 1ZIA has a minimum billable object size of 128K, and with the Glacier storage class, you will be paying for 40k¹ of metadata storage in addition to the object size in bytes).

Depending on the two regions involved, cross-region data transfer charges can be as low as $0.02/GB (or even $0.01/GB for the special case of us-east-1/us-east-2) which hardly seems burdensome if you need that additional level of assurance -- and note that since CRR also supports object versioning and can be configured not to replicate object deletion, it provides some protections against the risks that *you* pose to your own data -- risks that arguably exceed the systemic risks in S3 itself.

Other options are cross-cloud-provider replication, copying objects to GCS, for example, which would be more expensive due to data transfer costs but then can also fit into your "beyond worst case" disaster recovery plan for when AWS (or your entire AWS account?) is completely inaccessible. The cost of cross-cloud can be partially mediated by using aggressive compression where applicable, and services like Direct Connect, which reduces the cost of exporting data from AWS, particularly if the presence of the interconnection is justified by other purposes.

Or, consider the extreme opposite: a managed local backup strategy that makes physical, tangible backups on DVD or Blu-Ray is still better than no backup at all. I take a fair amount of grief for suggesting this "low tech" approach, but as long as the lifespan of the media is factored in and aggressive checksumming and integrity measures are in place, this is a viable protection against the extremely unlikely event where data is lost from S3. The only problem with this solution is that it appears to cost less than it really does -- it can be somewhat labor-intensive, requiring frequent touching of disks even when everything else is automated -- and of course if you compare the costs of this "simple" solution to the relative set-and-forget of cross-region replication, CRR becomes a pretty obvious choice.

---

¹ *40k* is an oversimplification, based on two values, 8k + 32k, mentioned in the Amazon S3 Developer Guide. *"For each archived object, Glacier adds 32 KB of storage for index and related metadata"* is straightforward enough, but the explanation of the remaining 8k is a bit less intuitive: *"For each object archived to Glacier, Amazon S3 uses 8 KB of storage for the name of the object and other metadata. Amazon S3 stores this metadata so that you can get a real-time list of your archived objects by using the Amazon S3 API... You are charged standard Amazon S3 rates for this additional storage."* When S3 migrates an object to the Glacier storage class, you are still able to access informarion about the object in bucket listings and access all the object's metadata in real time, just as any other S3 object, even though the object payload itself is stored in Glacier and not accessible in real time. This metadata is stored at the S3 `STANDARD` storage class rate, rather than the Glacier rate. It is unclear whether this is a fixed 8k, or actually a maximum, depending in part on the actual size of the object metadata, which includes but is not limited to the optional `x-amz-meta-*` user-defined metadata for each object. As such, the importance of this 8k as a cost consideration is not entirely clear. The 32k is noteworthy whenever it is significant in comparison to the total size of a small object.

---
Tags: amazon-web-services, data
---


# Question
Title: What is the difference between dockerd and com.docker.service in Docker for Windows?
What is the difference between *dockerd* and *com.docker.service* in Docker for Windows? Or rather I should ask: why do I need (if I need) *com.docker.service* running?

**Intention:** I want to use Docker only with command line in Windows environment in Windows container mode, control it with PS scripts etc. etc.

For me the role of *com.docker.service* is unclear.

I am able to run *dockerd* process and pull and run containers, when *com.docker.service* is stopped. When I start it - nothing happens (or maybe I don't notice the change).

# Answer
> 2 votes
dockerd is a persistent process that manages containers. Docker uses different binaries for the daemon and client. ( from Docker site ). Docker Daemon is a server which interacts with the operating system and performs all kind of services. The Docker Daemon listens for REST API request and performs the operation. Its process running on the background.

Docker service is the utility we use when we run any docker commands e.g. docker run (docker container run), docker images, docker ps etc. It allows us to run these commands which a human can easily understand.

---
Tags: docker, containers, windows
---


# Question
Title: Terraform: Provide credentials for docker hub registry
How would I provide docker hub credentials to a private image in the following example?

```
data "docker_registry_image" "ubuntu" {
  name = "ubuntu:latest"
}

resource "docker_image" "ubuntu" {
  name          = "${data.docker_registry_image.ubuntu.name}"
  pull_triggers = ["${data.docker_registry_image.ubuntu.sha256_digest}"]
}

```

# Answer
Docker registry credentials is seting up in provider configuration.

```
provider "docker" {
  registry_auth {
    address = "quay.io:8181"
    username = "someuser"
    password = "somepass"
  }
}

```

Also possible to set env variables DOCKER\_REGISTRY\_USER and DOCKER\_REGISTRY\_PASS
> 1 votes

---
Tags: terraform
---


# Question
Title: How to run a Windows container inside Windows Subsystem for Linux (WSL)?
I have managed to install docker on Windows, and I can run docker from my Ubuntu bash prompt of the WSL. But when I try to pull or run a Windows image from docker hub, I get the following error:

```
root@DESKTOP-J9B5HJG:~# docker info  -f '{{.OSType}}/{{.Architecture}}'
linux/x86_64
root@DESKTOP-J9B5HJG:~# docker pull mcr.microsoft.com/windows:1809-amd64
Error response from daemon: manifest for mcr.microsoft.com/windows:1809-amd64 not found
root@DESKTOP-J9B5HJG:~#

```

# Answer
> 4 votes
`C:\Users\romain.prevost>docker info -f '{{.OSType}}/{{.Architecture}}'
'linux/x86_64'`

Now, if you are running Docker for Windows, right click the Docker icon in your tray, and select "Switch to windows containers"

`C:\Users\romain.prevost>docker info -f '{{.OSType}}/{{.Architecture}}'
'windows/x86_64'`

Voilà! Essentially, Docker for Windows includes two different engines : Linux in a VM, and Windows, natively on your windows kernel. But soon, there will be options to run Linux containers natively on the Windows kernel. Exciting times!

# Answer
> 0 votes
To run windows container you need a windows docker engine. Have a look to this answer: https://stackoverflow.com/questions/42158596/can-windows-containers-be-hosted-on-linux

---
Tags: docker, dockerhub
---


title: Jenkins: What is a build?

text:
# Question
Title: Jenkins: What is a build?
I'm coming from Ops and I don't have a heavy software engineering background. In Jenkins, what is a "build" exactly and why is it named such? When I build a shell/powershell script, I'm not really compiling anything, am I? Then why is Jenkins "building" the source code. I thought building from source to binary is for compiled languages, unless Jenkis is using the word "build" in a more generic manner.

Please help me understand what's going on objectively.

# Answer
> 11 votes
As you guessed, *build* not necessarily means "compile". *Building* is a process of creating software from sources, which might include stuff like gathering dependencies, compiling, archiving, transforming code in any way, but also testing, deploying to different environments and promoting the artifacts between them.

# Answer
> 0 votes
It is important to understand the terms **Job** and **Build** from the jenkins standpoint.

In Jenkins, a user creates **job(s) which is typically a configuration for running autonomous tasks**. A job could be a task for building/packaging software, creating artifacts, deploying artifacts, creating help files, etc. This configuration may change from time to time.

Every time you run a job, Jenkins `compiles` the job configuration inside the project workspace to perform the defined steps. **Each run of this job is called as a build** and each step is called a `build step`. Since the environment around the job may change from build to build, any build may `Fail`(or become `Unstable`) during a run. Thus, the term - Build.

# Answer
> 0 votes
Well, there is a bit of a mixed terminology here and term transfer. Jenkins is using the word **Job** to mean *automation task* and **Build** to mean single *execution of the automation task* at the current state of system and possibly some variables as input. Traditionally a **Build** is a substitute term used for any process that produces **Derived Objects** (see my answer here) and this mixing of terms leads often to confusion in the entire CI/CD process that I've tried to explain here.

---
Tags: jenkins, terminology, build-pipeline, software-engineering
---


# Question
Title: Nginx routing setup within Docker container, request timing out with 502
I have a React application where a user can enter in some number, there is an algorithm that runs some calculation and spits out a result, but before we get there, Nginx is looking at the request and deciding whether to route it to React or Express server.

Well when the number is submitted, there is an xhr request that remains pending until it just times out with a 502 bad gateway error.

All this is happening inside of a Docker container.

I ran a `docker logs <container-id>` and kept seeing this:

```
upstream server temporarily disabled while connecting to upstream

```

I thought it might be a typo in my Express server or in my worker process or even in the React application but I find none, so I am left wondering if the issue has to do with how I built my `default.conf` file:

```
upstream client {
    server client:3000;
}

upstream api {
    server server:5000;
}

server {
    listen 80;

    location / {
        proxy_pass http://client;
    }

    location /sockjs-node {
        proxy_pass http://client;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
    }

    location /api {
        rewrite /api/(.*) /$1 break;
        proxy_pass http://api;
    }
}

```

I feel like my knowledge of Nginx configurations and upstream is limited to where something may not be correct about this setup. After running for awhile the whole application crashed.

To get this configuration to override the default `default.conf` inside of Nginx I setup a `Dockerfile.dev` inside of `nginx/` folder:

```
FROM nginx
COPY ./default.conf /etc/nginx/conf.d/default.conf

```

The application overall is using this `docker-compose.yml` file:

```
version: "3"
services:
  postgres:
    image: "postgres:latest"
  redis:
    image: "redis:latest"
  nginx:
    restart: always
    build:
      dockerfile: Dockerfile.dev
      context: ./nginx
    ports:
      - "3050:80"
  api:
    build:
      dockerfile: Dockerfile.dev
      context: ./server
    volumes:
      - /app/node_modules
      - ./server:/app
    environment:
      - REDIS_HOST=redis
      - REDIS_PORT=6379
      - PGUSER=postgres
      - PGHOST=postgres
      - PGDATABASE=postgres
      - PGPASSWORD=postgres_password
      - PGPORT=5432
  client:
    build:
      dockerfile: Dockerfile.dev
      context: ./client
    volumes:
      - /app/node_modules
      - ./client:/app
  worker:
    build:
      dockerfile: Dockerfile.dev
      context: ./worker
    volumes:
      - /app/node_modules
      - ./worker:/app

```

I am also wondering if the `default.conf` file is fine, but its my Express API that is taking too long to respond.

Then towards the bottom of the `docker-compose.yml` file I added some Redis environment variables I thought it may have needed below `worker`:

```
 worker:
    build:
      dockerfile: Dockerfile.dev
      context: ./worker
    volumes:
      - /app/node_modules
      - ./worker:/app
    environment:
      - REDIS_HOST=redis
      - REDIS_PORT=6379

```

I rebuilt the image with `docker-compose up --build` and restarted the application, and I can see the previous xhr requests still pending and they still give me a 502 and 504 error after a non-zero amount of time pending.

# Answer
> 1 votes
You will notice in this upstream block:

```
upstream api {
    server server:5000;
}

```

I called it `api` but then I say `server server:5000;`. That was the problem because I originally had it as:

```
upstream server {
    server server:5000;
}

```

but then thought that `server` might be a reserved operator in the Nginx world so I changed it to `api` but did not change it inside the block.

So it should have been:

```
upstream api {
    server api:5000;
}

```

After changing it, the xhr pending and timing out 502 errors went away.

---
Tags: docker, docker-compose, nginx
---


# Question
Title: How should CI/CD deploy to production environment - copy artifacts or git pull from the server?
We have an internal CI/CD server running private GitLab. It has the source code of our NodeJS project. We would like to run CI/CD and have it deploys to our on-premises production server. (Let's assume we are using the `master` branch).

Here are two most common methods I found on the internet:

1. Run `git pull` on the production server, run whatever build tasks needed (`npm install`, minify, etc...), and restart the service
2. Build the source codes on CI/CD server, rsync the built artifacts to production server and restart

Surprisingly, most of the examples I found on the internet uses method 1. This method requires the production server to have public internet access which may not be possible for many cases.

My question: is method 1 really the best way to deploy a NodeJS application to a production server? If yes, what is the reason?

# Answer
> 6 votes
There are lots of bad examples on the Internet. Doing a `git pull` to distribute code is fabulous for development, but prone to all sorts of issues in practice. It should not be used for production deploys without careful consideration of the negative consequences.

* What happens when somebody checks out a different branch? You'll be sad when you keep `git pull`ing and nothing new shows up.
* How do you verify that the machine is running the expected release? You can get this from `git`, but it is easier with most artifact systems.
* How do you release to machines that are on an air-gapped network? Simulating your `git` server on a private network will be a fun time for you.

I'm not sure what format `npm` uses for artifacts, but it is also probably a good idea to back them up off of the CI/CD server and use a dedicated set of machines for serving up the artifacts. If you spin up 100 machines at once would your CI/CD server handle it or fall over? Isolating the artifact serving will avoid your CI/CD server being swamped and useless until the deploy is over.

# Answer
> 2 votes
There are some source control systems that bill themselves as artifact management platforms as well (for example Perforce/Helix) and they try to support the mode of work. But git is especially bad at that. You would have to do a lot of work to make git support both development of code and management of artifacts efficiently. I'd suggest to not do that and use a different system for each. JFrog Artifactory for example is a great tool for that. Delivering code in containers and using docker hub for artifact store is another excellent way to do it. Even a bunch of upload/download scripts against S3 are better than storing your artifacts in git, as you might actively slow down the developer experience if you don't setup your solution exactly right.

---
Tags: continuous-integration, gitlab, node.js
---


# Question
Title: In jenkins, how to re-run old builds of a job?
Some old builds are failed in my jenkins job and I need to re-run them again. How to do that?

# Answer
> 7 votes
If the job is a jenkins pipeline, open the failed build and select the `Replay` option. Otherwise select the `Rebuild` option.

*Sample Replay Option*:

*Sample Rebuild Option*:

---
Tags: jenkins
---


title: Installing Helm charts using Terraform

text:
# Question
Title: Installing Helm charts using Terraform
I have been trying to install Helm charts using Terraform in a cluster which operates in GKE.

My question is in two parts:

1. Is it a good practice to use Terraform for installing Helm charts?
2. I have been getting this error when Terraform tries to install a Helm chart:

> helm\_release.release\_name: Get https://XX.XXX.XX.X/apis/extensions/v1beta1/namespaces/kube-system/deployments/tiller-deploy: dial tcp XX.XXX.XX.X:443: connect: connection refused

Here is how I am configuring the Helm chart:

```
provider "kubernetes" {

  host     = "${var.cluster-host}"
  username = "${var.cluster-username}"
  password = "${var.cluster-password}"

  client_certificate     = "${base64decode(var.cluster-client-cert)}"
  client_key             = "${base64decode(var.cluster-client-key)}"
  cluster_ca_certificate = "${base64decode(var.cluster-ca-certificate)}"
}

resource "kubernetes_service_account" "tiller" {
  metadata {
    name      = "tiller"
    namespace = "kube-system"
  }
}

resource "kubernetes_cluster_role_binding" "tiller" {
  metadata {
    name = "tiller"
  }

  role_ref {
    api_group = "rbac.authorization.k8s.io"
    kind      = "ClusterRole"
    name      = "cluster-admin"
  }

  # api_group has to be empty because of a bug:
  # https://github.com/terraform-providers/terraform-provider-kubernetes/issues/204
  subject {
    api_group = ""
    kind      = "ServiceAccount"
    name      = "tiller"
    namespace = "kube-system"
  }
}

provider "helm" {
  install_tiller  = true
  service_account = "tiller"
  namespace       = "kube-system"
  kubernetes {
      host     = "${var.cluster-host}"
      username = "${var.cluster-username}"
      password = "${var.cluster-password}"

      client_certificate     = "${base64decode(var.cluster-client-cert)}"
      client_key             = "${base64decode(var.cluster-client-key)}"
      cluster_ca_certificate = "${base64decode(var.cluster-ca-certificate)}"
  }
}

```

# Answer
> 1 votes
1. you can use terraform to install helm charts, you dont have to obviously
2. something is probably wrong with your kubernetes connection, check if its actually working

---
Tags: terraform, helm, gcp
---


# Question
Title: Why does the Jenkins bitbucket-build-status-notifier-plugin post the status to the shared pipeline library repository?
I am attempting to implement the Jenkins bitbucket-build-status-notifier-plugin, found here: https://github.com/jenkinsci/bitbucket-build-status-notifier-plugin

We used the shared-pipeline code functionality of Jenkinsfile, along with multibranch pipelines- all our Jenkinsfile code lives in one repo and each application makes only a parameterized call to a function in this repo.
The problem comes when the plugin posts status- it posts to the repo of the shared pipeline code, not the application being built! It is otherwise working correctly, authenticating and posting status quickly.

The plugin is not parameterized to allow me to pass in a commit ID- meaning that this is being derived from an environment variable, presumably in a novel way that other plugins are not using. The plugin specifically cites changes to facilitate Jenkinsfile and multi-branch pipelines. I suspect I may have a race condition with the scm checkout command, perhaps the bitbucket plugin is being initialized before any call to scm checkout is made?

Does anyone have any advice on debugging this? jenkins.err does not contain any errors, since nothing is throwing. Is there an environment variable I can change in order to force a context switch from the shared pipeline code repo to the application code repo?

# Answer
This is a known bug. See JENKINS-42878 and JENKINS-41996. This bug has been resolved upstream, which means you should be able to fix the bug by upgrading the plugin to the latest version.
> 4 votes

# Answer
Based on this PR, the `repoSlug` was added and now the status is sent to the right repository.

When it was not working:

```
post {
    success {
        bitbucketStatusNotify(
                buildState: 'SUCCESSFUL',
                commitId: env.GIT_COMMIT
        )
    }
    failure {
        bitbucketStatusNotify(
                buildState: 'FAILED',
                commitId: env.GIT_COMMIT
        )
    }
}

```

Now it works:

```
post {
    success {
        bitbucketStatusNotify(
                buildState: 'SUCCESSFUL',
                repoSlug: 'repoSlug aka repositoryName, e.g. some-app',
                commitId: env.GIT_COMMIT
        )
    }
    failure {
        bitbucketStatusNotify(
                buildState: 'FAILED',
                repoSlug: 'repoSlug aka repositoryName, e.g. some-app',
                commitId: env.GIT_COMMIT
        )
    }
}

```

The README in the Github repo emphasized that:

> Note that the repoSlug and commitId parameters work only when they are both specified.
> 3 votes

# Answer
One could also use bcbsn as a replacement. This tool associates the build status with the right commit and sends the build status to the right repository.
> 0 votes

---
Tags: jenkins, jenkins-pipeline, jenkins-plugins, jenkinsfile
---


# Question
Title: What options are available to report the build status of Jenkins Multi Pipeline's first branch build on k8s to bitbucket-cloud?
**Background**

The Bitbucket Status Notifier plugin has been configured. The status was reported, but since more and more jobs have been moved to Jenkins-on-steroids that is running on k8s, buildStats are not reported if a branch is built for the first time.

**Aim**

The aim is to report the build status to bitbucket-cloud by jenkins multi-branch when a branch is built for the first time.

**Attempts to solve the issue**

This related issue was found and a comment was added on Jenkins' Jira.

As a workaround, this suggestion was tried, but it caused a couple of issues and it is not a permanent solution.

> ```
> def call(buildId, jobName) {
>     if ("${buildId}" == "1") {
>         build job: "${jobName}", wait: false
>         currentBuild.result = 'ABORTED'
>         error("Skipping build ${buildId} as it doesn't play nice with bitbucket notifications")
>     }
> }
>
> ```

**Questions**

The question is twofold.

* First, what other options are available to report build statuses from jenkins-on-steroids to **bitbucket-cloud** that also work if a build is run for the first time in a branch `(BUILD_ID==1)` if the multi-branch plugin is used?
* Second, if the first question cannot be answered, what steps could be taken to solve the bug?

# Answer
As I was not able to tackle the bug in the Java code and the bug was already reported in 2017 I decided to write this plugin. This binary is able to send a build status even when a branch is built for the first time.
> 1 votes

---
Tags: kubernetes, jenkins-pipeline, builds, bcbsn
---


# Question
Title: Jenkins SSH connection on remote server immediately closes after login
I created a user for jenkins on my remote server that worked previously just fine, but now when I try to login with shh on the server the connection closes immediately after login. This is strange because on the website that is hosting jenkins it seem to work just fine, I can log there with chrome no problem and it evan builds succefully. My only problem is when I SSH with that user jenkins on the server. Will add here the ssh -v logs when I get disconnected:

```
debug1: client_input_channel_req: channel 0 rtype exit-signal reply 0
debug1: client_input_channel_req: channel 0 rtype eow@openssh.com reply 0
Last login: Tue Mar 12 09:21:23 2019 from 82.78.220.8
debug1: channel 0: free: client-session, nchannels 1
Connection to 145.239.84.136 closed.
Transferred: sent 2652, received 3604 bytes, in 0.5 seconds
Bytes per second: sent 5268.4, received 7159.7
debug1: Exit status -1

```

This is what I get after I insert the password.

I will also post the sshd logs:

```
Accepted password for jenkins from 82.78.220.8 port 40872 ssh2
pam_unix(sshd:session): session opened for user jenkins by (uid=0)
Received disconnect from 82.78.220.8 port 40872:11: disconnected by user
Disconnected from 82.78.220.8 port 40872
pam_unix(sshd:session): session closed for user jenkins

```

I have this setup in the passwd:

```
jenkins:x:113:118:Jenkins,,,:/var/lib/jenkins:/bin/bash

```

I have to add that I can ssh with other users on the server just fine. I also tryed to **su jenkins** from root: This will just freeze my terminal and will open something like this:

```
jenkins@vps531680:/root$ root@vps531680:~# root@vps531680:~# logout

```

and I will get disconnected.

I also tryed this **sudo usermod -s /bin/bash jenkins**:

```
bash: /root/.bashrc: Permission denied
jenkins@vps531680:~$ Killed

```

On the weird side is that if I just reboot the server, for like 5-10 mins after that my jenkins user works just fine, but I will get disconnected after that time and I won't be able to SSH again, only after another reboot and for 5-10 mins. Any advice will be apreciated!

# Answer
> 1 votes
Check to see if the home directory for Jenkins was created?

`/home/jenkins`

---
Tags: jenkins, servers
---


# Question
Title: How do i specify the path of a Dockerfile using Blue Ocean
I want my pipeline created using Blue Ocean (Jenkins) to build with a dockerfile that is not in the root of the git repo. How do I achieve this?

Our git repo is a collection of sub-projects with each containing it's own dockerfile. So we cannot place them in the root directory.

# Answer
From the official instructions on building Docker images with Jenkins Pipeline:

> The `build()` method builds the `Dockerfile` in the current directory by default. This can be overridden by providing a directory path containing a `Dockerfile` as the second argument of the `build()` method, for example:
>
> ```
> node {
>     checkout scm
>     def testImage = docker.build("test-image", "./dockerfiles/test")
>
>     testImage.inside {
>         sh 'make test'
>     }
> }
>
> ```

I'm not sure if you can create a Pipeline (i.e. Jenkinsfile) with this exact configuration through the Blue Ocean UI, but I would imagine you can. However, I personally have found using Blue Ocean to create pipelines to be finicky at best, so I would recommend going over a Jenkinsfile created by Blue Ocean and making tweaks and adjustments by hand anyway. This would give you the opportunity to adjust the Dockerfile location even if you aren't able to do it via Blue Ocean.
> 1 votes

# Answer
```
node {
checkout scm
app = docker.build("test-image","-f path/to/dockerfile .")
}

```
> 1 votes

---
Tags: docker, jenkins, dockerfile, jenkins-blueocean
---


# Question
Title: Preinstall packages for a nodejs Docker Image according to package.json
I would like to prepare a Docker image for a nodejs project. The developers use package.json to list their node module dependencies. I would like to prepare the Docker image (as base on the Dockerfile), with most of the node\_modules already installed "globally" on the image.

Is there a best practice to prepare nodejs images?

# Answer
Depend of life cycle of you app, because Node libraries and dependences change or end life to obsolet, so if you app constant change version to deploy, you can use docker tag for describe version or time when it build image, is a good practice, so Dockerfile shall copy package.json, and too look when you need change image source OS, by example change ubuntu linux to alpine , many dependences or how to install "npm" and dependences for node, a example:

```
  FROM alpine:3.8

# Update
RUN apk add --update nodejs nodejs-npm

# Install app dependencies
COPY package.json /src/package.json

RUN cd /src; npm install

# Bundle app source
COPY . /src

EXPOSE 5000
CMD ["node","src/index.js"]

```

well , hope it help you
> 1 votes

# Answer
Assuming this is a production `Dockerfile`, the boilerplate configuration for a Nodejs type of application would look like this:

```
FROM node:alpine as builder
WORKDIR '/app'
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

```

or like this:

```
FROM node:alpine
WORKDIR "/app"
COPY ./package.json ./
RUN npm install
COPY . .
CMD ["npm", "run", "start"]

```

and if you involve Nginx, you may additionally have a couple of lines that would look something like this:

```
FROM nginx
EXPOSE 80
COPY --from=builder /app/build /usr/share/nginx/html

```

So now you have a couple of answers with a few variations of how you could write out the production ready `Dockerfile`.
> 1 votes

---
Tags: docker, dockerfile, node.js
---


# Question
Title: Organizing the build steps on AzureDevOps
I am new on DevOps world and I am making my first build/release pipeline for a .net web application using Azure DevOps. On the picture bellow, I just add some build steps and create some tasks groups to avoid duplications on the builds (that are similar). I have the `Run on agent` that I called it as `Qa Agent Job` which runs over the local build agent hosted on my build server (as a windows service).

My question is related with organization. I have some build steps here and I would like to organize it by sessions, for sample, Nuget Restore, Versioning, Build, Testing, Building services, Publishing artifacts etc. Is that a problem to organize it using the `Run on agent` item on build step? Should I lost any performance like "connecting on the server again" or "start a new process" or something like that?

Thank you.

# Answer
> 1 votes
You can separate the steps, especially as it would let you do divide the work among different agents. You can also leave them in a single agent if you wish.

The primary advantage I see is leveraging different pools for different sets of work.

With releases last I checked variable scope was limited (as of 2018) to the "phase".

I wouldn't necessarily worry about performance due to connections unless you've observed this issue and have more specific detail you can add.

---
Tags: azure-devops, build-pipeline, release
---


# Question
Title: Multiple levels of parallel stages in a Jenkins declarative pipeline
I need to define a declarative pipeline with multiple levels of parallel stages as such:

```
1   Prebuild_action1
2   Prebuild_action2
3.1 Build platform_1
4.1   Test1 platform_1
4.2   Test2 platform_1
4.3   Test3 platform_1
3.2 Build platform_2
3.3 Build platform_3
3.4 Build platform_4

```

First, 1 should run, then 2 should run, then all of 3.x should run in parallel and when 3.1 is done all 4.x should run in parallel.

It doesn't seem possible for two reasons: 1. There doesn't seem to be any way to have both a stage and a group of parallel stages within a parent stage and it seems that parallel blocks can only be defined at top-level stages so I can't have a parallel block for 3.x and 4.x.

Is there some way to do that I am just not seeing at the moment?

# Answer
> 5 votes
Sure it's possible to have nested parallel stages and it works just fine (I've done it before), but the visualization in the web UI is terrible, even with Blue Ocean. There was even an official blog post when this feature was added.

This question has already been asked a couple other times on this site as well, you might be interested in these questions and answers:

It's not entirely clear to me from the wording of your question if it's a duplicate of those questions or if there are significant differences, so I haven't flagged your question as a duplicate.

---
Tags: jenkins, jenkins-pipeline
---


# Question
Title: Terraform - referencing existing security group
Is there a way I can associate existing security group to RDS that is going to be created or the only way is to recreate the security group so it can be added to the state file?

# Answer
You can retrieve security group from data source

```
variable "security_group_id" {}

data "aws_security_group" "selected" {
  id = "${var.security_group_id}"
}

```
> 3 votes

# Answer
I didn't use list square brackets, the functionality is there as documented, just list brackets and group id. e.g.: vpc\_security\_group\_ids = \[ "sg-dfe8e2bf" \]
> 0 votes

# Answer
You can use the *terraform import* command to import the security group so you can reference it as a created Terraform resource.

https://www.terraform.io/docs/providers/aws/r/security\_group.html
> 0 votes

---
Tags: terraform
---


# Question
Title: How is Ansible different from simply running a provisioning bash shell in Vagrant?
A team of IT sysadmins that have exprience using shell scripting to solve their problems, are contemplating to start using Ansible instead.

**Are there substantial differences and good reasons to start using Ansible vs. to continue writing shell scripts?**

# Answer
> 41 votes
I never used Ansible but since a few weeks, I try to figure out what good Ansible could be in comparison with shell scrips–Which proves, at least in my case, that the haunting ad-campaigns they run are effective! After many unsuccessful attempts–which proves how their documentation fail at answering one of the most obvious question–I think I finally got it.

My conclusion is that over shell scripting, Ansible essentially offers 1. The possibility of checking that a system agrees with a desired state, 2. the ability to integrate with Ansible Tower, which is a paying system that seems to include monitoring abilities. In some important cases, like when implementing the immutable server pattern, the point 1 is probably not very useful, so the list of advantages is rather thin.

It seems to me that the benefits offered by Ansible over shell-scripting, as the documentation present them, could be sensible in a few handful of optimistic cases well covered by available modules but are small or even hypothetical in the general case. For a skilled shell-programmer, these benefits are most likely counter-balanced by other aspects of the trade-off.

But my conclusion maybe only proves how bad the introduction material is at displaying the actual advantages of this software!

Now, I propose to watch the introduction video and go randomly as a potential new user through the introduction material to Ansible an let's compare it to what a skilled shell programmer can produce in a reasonable time.

# The quick start video:

There is a quick start video. It starts with a page claiming that… well these are not really claims, these are bullet lists, an artefact commonly used to suspend critical judgement in presentations (since the logic is not shown, it cannot be criticised!)

### 1. Ansible is simple:

1.1 Human readable automation – Specifications are technical documents, how could

```
  name: upgrade all packages
  yum:
    name: '*'
    state: latest

```

be easier to read than the corresponding *yum* invocation found in a shell-script? Furthermore, anybody who had contact to AppleScript dies laughing when they read “human readable automation.”

1.2 No special coding skills required – What is coding if not writing formal specifications? Ansible has conditionals, variables, so, how is it not coding? And why would I need something I cannot program, that would henceforth be inflexible? The statement is happily inaccurate!

1.3 Tasks executed in order – Well, maybe some codegolf aficionados are aware of languages that execute tasks in disorder, but executing tasks in order hardly looks exceptional.

1.4 Get productive quickly – Skilled shell programmers are productive now. This counter-argument is just as serious as the initial argument.

### 2. Ansible is powerful

A popular salesman trick to sell artefacts is to fool people into believing they will acquire the “power” of these artefacts. The history of advertisement for cars or isotonic drinks should supply a convincing list of examples.

Here Ansible can do “app deployment” – but shell script surely do, “configuration management” but this is a mere statement of the purpose of the tool, not a feature, and “workflow orchestration” which looks a bit pretentious but no example in this document goes beyond what GNU Parallel can do.

### 3. Ansible is agentless

To populate the column, they wrote in three different manners that this only needs *ssh,* which, as everybody knows is a *daemon* and has nothing to do with these *agents* pervading the world of configuration management!

### The rest of the video

The rest of the video introduces inventories, which are static lists of resources (like servers) and demonstrates how to deploy Apache on three servers simultaneously. This really does not match the way I work, where resources are highly dynamic and can be enumerated by command-line tooling provided by my cloud provider, and consumed by my shell functions using the pipe `|` operator. Also, I do not deploy Apache on three servers simultaneously, rather, I build a master instance image that I then use to start 3 instances which are exact replicas one of the other. So the “orchestrating” part of the argumentation does not look very pertinent.

# Random documentation step 1: Integration with EC2

EC2 is the computing service from Amazon, interacting with it is supported by some Ansible module. (Other popular cloud computing providers are also provided.):

```
# demo_setup.yml

- hosts: localhost
  connection: local
  gather_facts: False

  tasks:

    - name: Provision a set of instances
      ec2:
         key_name: my_key
         group: test
         instance_type: t2.micro
         image: "{{ ami_id }}"
         wait: true
         exact_count: 5
         count_tag:
            Name: Demo
         instance_tags:
            Name: Demo
      register: ec2

```

The corresponding shell-script would be essentially identical with YAML replaced by JSON:

```
provision_a_set_of_instances()
{
  aws --output=text ec2 run-instances --image-id …
}

```

or the JSON version

```
provision_a_set_of_instances()
{
  aws --output=text ec2 run-instances --cli-input-json "$(provision_a_set_of_instances__json)"
}

provision_a_set_of_instances__json()
{
  cat <<EOF
{
    "ImageId": …
}
EOF
}

```

Both version are essentially identical, the bulk of the payload is the enumeration of the initialisation values in a YAML or JSON structures.

# Random documentation step 2: Continuous Delivery and Rolling Upgrades

The largest part of this guide does not display any really interesting feature: it introduces variables (IIRC, shell scripts also have variables)!, and an Ansible module that handles mysql, so that if instead of searching after “how do I create a mysql user with privileges on X Y” and end with something like

```
create_application_db_user()
{
  mysql --host "${mysql_host}" --user "${mysql_user}" --password "${mysql_password}" "${mysql_table}" <<EOF
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%';
EOF
}

```

you search after “how do I create a mysql user with privileges on X Y in *ansible*” and end up with

```
- name: Create Application DB User
  mysql_user: name={{ dbuser }} password={{ upassword }}
              priv=*.*:ALL host='%' state=present

```

The difference is still probably not very meaningful. On that page we also discover that Ansible has a template meta-Programming language

```
{% for host in groups['monitoring'] %}
-A INPUT -p tcp -s {{ hostvars[host].ansible_default_ipv4.address }} --dport 5666 -j ACCEPT
{% endfor %}

```

When I see this, I happen to really be in my comfort zone. This kind of simple meta-programming for declarative languages is exactly the same theoretical paradigm as BSD Makefiles! Which I happen to have programmed extensively This excerpt shows us that the promise of working with YAML file is broken (so I cannot run my playbooks through a YAML parser, *e.g.*). It also shows us that Ansible must discuss the subtle art of evaluation order: we have to decide if variables are expanded at the “declarative part” of the language or at the “imperative” meta-part of the language. Here shell programming is simpler, there is no meta-programming, aside from *explicit* `eval` or external-script sourcing. The hypothetical equivalent shell excerpt would be

```
enumerate_group 'monitoring' | {
  while read host; do
    …
  done
}

```

whose complexity in comparison to the Ansible variant is probably tolerable: it just uses the plain, regular, boring constructs from the language.

# Random documentation step 3: Testing strategies

Last, we meet what turns out to be the first actually interesting feature of Ansible: “Ansible resources are models of desired-state. As such, it should not be necessary to test that services are started, packages are installed, or other such things. Ansible is the system that will ensure these things are declaratively true. Instead, assert these things in your playbooks.” Now it starts to be a bit interesting, but:

1. Aside from a handful of standard situations readily implemented by available modules, I will have to feed the bits implementing the test myself, which will quite probably involve some shell commands.
2. Checking for the conformity of installations might not be very relevant in the context where the immutable server pattern is implemented: where all systems running are typically spawned from a master image (instance image or docker image for instance) and never updated – they are replaced by new instead.

# Unaddressed concern: the maintainability

The introductory material from Ansible ignores the question of the maintainability. With essentially no type system, shell-scripting has the maintainability ease of JavaScript, Lisp or Python: extensive refactorings can only be achieved successfully with the help of an extensive automated testsuite – or at least designs that allows easy interactive testing. That said, while shell scripting is the lingua franca from system configuration and maintenance, nearly each programming language has an interface to the shell. It is therefore totally feasible to leverage the maintainability advantage of advanced languages, by using them to glue together the various the bits of shell-configuration bits. For OCaml, I wrote Rashell that essentially provides a hand of common interaction patterns for subprocesses, which makes the translation of configuration scripts to OCaml essentially trivial.

On the side from Ansible, the very weak structure of playbooks and the presence of a meta-programming feature make the situation essentially as bad as it is for shell scripting, with the minus points that it is not obvious how to write unit tests for Ansible, and the argument of introducing ad-hoc a higher-level language cannot be mimiced.

# Idempotency of configuration steps

The documentation of Ansible draws the attention on the necessity of writing idempotent configuration steps. More precisely, configuration steps should be written so that the step sequence *a b a* can be simplified to *a b*, i.e. we do not need to repeat configuration step. This is a stronger condition than idempotency. Since Ansible allows playbooks to use arbitrary shell commands, Ansible itself is unable to guarantee that this stronger condition is respected. This only relies on the programmer's discipline and the importance of this variation of idempotency when writing configuration scripts is certainly not a novelty.

---

Post-Scriptum. Since this answer seems to enjoy a relative popularity, I fixed a few embarrassing syntax errors and typos. By a twist of life I also had to use Ansible two years in my work. Overall my experience confirms what I foreseen here and I hardly can think about a situation where shell scripts would have been really outperformed by Ansible. On some aspects, Ansible is just worse than shell scripting. At least the shell has functions, these functions can be mocked, it is possible to test part of all of them, so overall the shell has much better software engineering features than Ansible has. In a shell script it is also possible to process data and **awk** can express all what SQL can, which is very important when programming configuration – the information we are working with here is not intrinsically hierarchical, so there is a need for extracting an rewriting. Ansible is so bad at extracting and rewriting data! Treatments must be expressed with a mixture of YAMl-templating at the playbook step level and a dialect of Jinja at the dictionary member level… this is cumbersome, ugly, hard to write, hard to test and poorly documented (I regularly looked up the Jinja filter implementations!).

# Answer
> 25 votes
When you put it this way, even if Ansible has some inherent advantages, the benefits of using familiar tools (in this case shell scripting) must be outweighed. I don't think there's a clear cut answer to that.

If the team can achieve the things Ansible offers with shell:

1. Declarative, idempotent configuration management
2. Access to re-usable snippets (i.e. playbooks) for industry popular services.
3. Reliable management of remote execution, with retrying, rolling logic, etc.

then they could probably stick with what they know.

After all, you can implement "guards" in BASH. You can find lots of BASH existing work out there to solve a variety of server configuration tasks (essentially any Dockerfile out there is 90% bash installation code). You can get pretty close to what Ansible/Salt/Chef-Zero offer you, without actually having to port your entire existing solution to those tools.

It's a balancing act between NIH (not invented here) tendencies, and throwing out good, established scripts in favor a more robust solution.

One final consideration to keep in mind: how does your technology stack measure up when you try to recruit more people to the team. Finding people who have Ansible experience is a lot easier than finding people who have experience in your particular home-grown scripting CM tool. This isn't strictly a technical consideration, more a cultural one. Do you want to be the weird org that invents its own Ansible, or do you want to be the reasonable org that finds the right tool for the job? Those decision impact your ability to draw talent.

# Answer
> 14 votes
The above answer covers part of it but misses one of the important elements: convergent design. I wrote some words a while ago about this in the context of Chef at https://coderanger.net/thinking/ but the short version is that a bash script is a set of instructions, while an Ansible playbook (or Chef recipe, Salt state, etc) is a description of desired state. By documenting the state you want rather than the steps you want to take to get there, you can cope with a lot more starting states. This was the heart of Promise Theory as outlined in CFEngine long ago, and a design which we (the config management tools) have all just been copying since.

tl;dr Ansible code says what you want, bash code says how to do a thing.

# Answer
> 4 votes
It's 2019 and I've just spent a few days on an ansible learning curve and here is the absolute truth: Ansible isn't worth the trouble.

it's not finished, it doesn't run on windows and the combination of YAML config and misleading error messages will make your eyes bleed. It seems almost deliberately terrible and I mean that seriously. It's clearly the product of a redhat sysadmins frustrated developer side project. Probably a hipster.

If you don't require any.of its features beyond provisioning, and you are only ever provisioning on one particular OS. For pities sake write a decent shell.script.

As of right now, the whole project reminds me of early linux forums where noobs were told to RTFM and derided for asking why someone couldn't write a GUI for configuring graphics settings. You just don't get it do you? You should stick to windows... perhaps I will mate.. happy VI-ing.

Use Docker. In preference to anything. Docker is outrageously simple and powerful.

But what if you absolutely must provision on pre-existing tin? What are the real alternatives?

Well... there aren't any, yet. But I will promise you this, unless ansible gets better, there will be soon. Because no matter how hard the fanboys push it, and forgive it's failings... it's a 5 out of 10 for effort.

SCP up a bash script, and save yourself the trouble.

# Answer
> 3 votes
One thing worth noting that you will have less issues in running your ansible playbooks on remote hosts too. As it's the main reason for running ansible. When you are using shell scripting you still need to have a way to script the scp'ing to the remote host.

---
Tags: ansible, shell-script
---


# Question
Title: Google Cloud Registry and multiple projects
Is it possible to pull images from the same `GCR` from multiple `GCP` projects without making the registry public?

I want to do this so I do not have to upload multiple times the same image to multiple registries so it can be used on different projects.

# Answer
> 3 votes
Yes, it's possible. Fundamentally GCR is built on top of Cloud Storage, with roughly the same basic access control:

* public, i.e completely accessible
* private, with quite flexible access control from pretty much anywhere, even from outside the GCP domain - being in a certain GCP project is rather irrelevant.

From Granting users and other projects access to a registry:

> To give specific users or container clusters running on other projects permissions to pull images from a registry, you need to grant read permission on the underlying Cloud Storage bucket.
>
> ...
>
> 4. Select the **Permissions** tab.
> 5. Click **Add members**.
> 6. From the menu that appears, fill the **Members** field with the email addresses of users needing read permission, separated by commas. This email address can be one of the following:
>
> * a Google account (for example, `someone@example.com`)
>     * a Cloud IAM service account
>     * the Compute Engine default service account of another project. This account is used by the Google Kubernetes Engine to pull container images clusters by default. It is in the form `[PROJECT_NUMBER]-compute@developer.gserviceaccount.com`, where `[PROJECT-NUMBER]` is the GCP project number of the project that is running the Google Kubernetes Engine cluster.

There are some differences from Cloud Storage, most notable ones being:

* access control applies to the bucket level only, object level access is ignored
* GCR can only have a single bucket per GCP project

---
Tags: docker, gcp
---


# Question
Title: git - develop base and extended feature - commits in base should reflect in extended in pull
Hie I am working around in git to achieve something like mentioned below.

Imagine there is a Big feature which is going to develop - since it's very big they have split into core feature and an extended feature.

Now they have divided into teams for development.

Now how to make branches in a below-mentioned way

the core will be developing in core\_branch extended will be developing in extended\_branch containing core development it should be like that when we perform git pull in extended\_branch it has to pull if any commits made to core\_branch how to achieve this??

I am aware of git rebase / git merge. In either of the cases, extended team/developers have to check any new commits in the core branch and merge/rebase their extended\_branch

# Answer
> 1 votes
Because you have a large project with multiple teams using multiple development branches will give you merge headaches, especially if the core and extended features have a significant overlap in the codebase.

The extended feature team(s) will spend a lot of time periodically merging the core feature changes and dealing with the fallout from each such merge, which can not be properly/realistically estimated ahead of time. If there are multiple teams working on the extended feature they might decide to go on separate branches to further isolate and protect themselves against these periodic merge instabilities. It's just an illusion, that'll make things even worse at the overall project level - it can lead to Branch Merge Hell.

You may want to take a look at Trunk-Based Development (TBD), with and/or branch by abstraction. Most effective when using a gated-commit CI system.

---
Tags: git, github, software-engineering
---


# Question
Title: How to assign saltstack pillar values from Jenkins comma separated input parameters?
I have a Jenkins job with string parameter as target "server1,server2". Jenkins pipeline script is expected to execute the job on server1 and server2 respectively. There is a common salt sls file that updates directory permissions and groups on both servers. The expectation is when the job is executed on server1, a group by name xx-server1-yy must be created and updated in server1, similarly a group xx-server2-yy be created in server2 only. One sls file for Jenkins job on multiple servers with groups created specific to each server. What is the best approach?

# Answer
You didn't say how the sls file is executed.

```
salt '*' state.apply ftpsync pillar='{"ftpusername": "test", "ftppassword": "0ydyfww3giq8"}'

```
* Or you can set the group name as a grain on the minion in advance.
* Yet another way would be to set the group name as a jinja variable in the sls formula, depending on the hostname grain. Assuming your host names are set and standardized.
> 1 votes

---
Tags: jenkinsfile, salt, groovy
---


# Question
Title: What are the best practices of merging dev to master?
We have 2 branches (master/dev) + some feature branches and 2 environments (production/dev). Our team is a very small people. What are the best practices of merging dev to master?

* Every morning?
* After integration tests?
* How about merging master with dev and then testing (hotfixes) then merging master to dev?
* Some release branches?

I don't want to create anything too complicated.

# Answer
> 3 votes
You can use "git flow" or more simple "gitlab flow".

Our small team merge into master on release or sprint ends.

# Answer
> 1 votes
There are many theories about git branching models. You know about "git flow" https://nvie.com/posts/a-successful-git-branching-model/

But in practice that will slow you down in most cases. Remember Amdahl's law - put the effort where the usage is. At my workplace we only branch when making a merge request. This way we won't have to work for days with sham work like "merge to master" which will create impediments just because somebody was branching for the sake of branching. That works for us.

So I suggest that you commit to master and only branch when making a merge request. This is almost controversial in some cases, but I am all open for discussion.

# Answer
> 0 votes
It depends, pull request reviews should be done before merging to master. If you are using CI/CD, that would occur as often as you can schedule releases. I prefer the fork and pull request workflow, keeping the base repository cleaner. The devs can organize how they choose on their ends in their forks as long as they are routinely fetching from the base master branch.

If a dev quits, no one wants to be confused by what he/she was working on, so there is a plus with fork and pull there as well. Likely the next guy will start over from the approved master branch anyway.

Integration tests happen after merge to master, then there are conditions that must be met prior to release within the CI/CD pipeline that if not met will break the build. Use the same branch for all environments, with environment variables if there are differences in environments. You can use labels or the merge requests themselves to describe what’s released. You don’t necessarily need feature branches. It just depends on the complexity of your project(s) and your team. More branches = more complicated from my perspective, particularly with dependencies on multiple repositories. Don’t tell the devs how to work, if you can avoid it, just set the requirements for approvals, rollbacks, and workflows necessary to guarantee you can report effectively to your management. Keep it simple. Good devs will figure out how to work together on their own.

---
Tags: continuous-integration, git, continuous-deployment
---


title: compiled opencv copy to another host

text:
# Question
Title: compiled opencv copy to another host
Every time I spawn a new host I need to compile OpenCV on Ubuntu following official manual. The problem is that it takes about 20-30 minutes depends on the VM type. Is it somehow possible to store the compiled OpenCV i.e. at S3 as a package or any othey way to avoid compilation?

create a VM image doesn't fit my purpose

# Answer
> 1 votes
If the end result would be entirely contained in a directory somewhere you could simply archive that directory after the installation on one machine and restore it on the new machine. It does work for *some* apps.

But after going through the Ubuntu 18.04: How to install OpenCV procedure and peeking into the makefiles I believe this wouldn't be applicable to OpenCV: its artefacts are spread in various places on a Ubuntu system.

But I *think* it's possible to significantly reduce the installation time by skipping the actual build process, which appears to be the bulk of the process. From the above referenced procedure (which I'll also use in describing the proposed solution):

> This process may take 30 minutes or longer, so go for a nice walk if you are able.

I'll re-use the referenced procedure for describing the proposal, with a few tweaks (I'd like to think that the tweaks would easily be portable to future/similar versions of the procedure):

**In the initial installation:**

* after the build completes but before the **Installing and verifying OpenCV** step insert:

**Step 4a: save the pre-built official OpenCV source tree to S3**

Follow Copying from s3 to EC2 instance instructions for S3 access setup, then run:

```
tar cvfz pre_built_opencv.tgz opencv*
s3cmd put pre_built_opencv.tgz s3://<bucket_name>

```

Optional: you can remove the local archive copy now:

```
rm pre_built_opencv.tgz

```

**In the subsequent installations:**

* replace **Step #2: Download the official OpenCV source** with:

**Step #2: Extract the pre-built official OpenCV source tree from S3**

Follow Copying from s3 to EC2 instance instructions for S3 access setup, then run:

```
cd ~
s3cmd get s3://<bucket_name>/pre_built_opencv.tgz pre_built_opencv.tgz
tar xvzf pre_built_opencv.tgz

```

Optional: you can remove the local archive copy now:

```
rm pre_built_opencv.tgz

```
* in **Step #4: Configure and compile OpenCV for Ubuntu 18.04**:

+ skip the **Configure OpenCV with CMake** section
    + replace the **Compiling OpenCV on Ubuntu 18.04** section with:

    **Enter the pre-built OpenCV build directory**

    ```
    cd ~/opencv/build

    ```

I didn't run it myself, but I think it *should* work, at least for VMs of the same type.

I'd 1st try the same even for different VM types. If that doesn't work then I'd re-run the initial installation for them, using a different archive filename.

---
Tags: amazon-ec2, amazon-s3
---


# Question
Title: Accessing External REST api From Wthin Kubernetes Cluster
This is my first foray into Kubernetes land... I'm still pretty shaky on how things work and still wrapping my head around some of the concepts so please bear with me there.

The application I am deploying needs access to a couple of external third party http rest apis. What I **believe** I need from reading the docs is a service with an endpoint that points to the external rest apis ip. This is what I have in my helm templates:

service.yaml:

```
apiVersion: v1
kind: Service
metadata:
  labels:
    run: external_rest_service
  name: external_rest_service
spec:
  ports:
  - port: 443

```

My endpoint.yaml:

```
kind: Endpoints
apiVersion: v1
metadata:
 name: external_rest_service
subsets:
 - addresses:
     - ip: https://www.someservice.com/api
   ports:
     - port: 443

```

This of course doesn't work because ip needs to be an ip address. However, when I do an nslookup of the rest api I get back 3 different ip addresses which I believe may be because of round robin dns. Oddly when I try any of the ip addresses directly via curl I don't get a response. My questions are..

* Is this the correct or best practice approach to giving access to an outside resource from within my cluster?
* Can I configure (and should I) configure Kubernetes to allow access via domain name instead of ip? If so.. where do I configure this? I'm not seeing it when searching the docs.

If anyone could give me any guidance here I would really appreciate it. Thanks much!

# Answer
Usually to access an external API you can just use its URL. But you can create a Service for it if you like, the type of service should be ExternalName as described in the documentation https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types
> 1 votes

# Answer
A service in kubernetes is (mostly) used for internal communication. If you want to access an external resource by domain/ip you can just do so. If you have an IP address and you would like to have some sort of domain connected to it, you could you am service with the external name field set to the up address (we use that for database purposes). An endpoint is automatically created for you when you create an service so you don’t nees to bother with that
> 1 votes

---
Tags: kubernetes, helm, dns
---


# Question
Title: TravisCI build continues to fail even after changing alpine version
So I ran my Docker build with TravisCI and I got a failure like so:

```
FAIL src/App.test.js
  ● Test suite failed to run
    TypeError: Cannot assign to read only property 'Symbol(Symbol.toStringTag)' of object '#<process>'
      at exports.default (node_modules/jest-util/build/create_process_object.js:15:34)

```

I did not think that this `App.test.js` file would give me problems after I removed the logic from within the `it` block like so:

```
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";

it("renders without crashing", () => {});

```

I thought the issue may have been the latest release of `node` because I saw others have similar error messages, so I changed my version like so:

`FROM node:10.15-alpine as builder` OR `FROM node:10.15-alpine` as I have various `Dockerfile`s for each service I am building as this is a multi-container project.

That change I made did not resolve the issue, TravisCI continues to fail my build with the same exact error, what gives here?

I thought perhaps the issue would be a version of Jest mismatch, but I have not installed any version of Jest, this is my `package.json` file inside my `client/src/App.test.js`:

```
{
  "name": "client",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "react": "^16.8.3",
    "react-dom": "^16.8.3",
    "react-scripts": "2.1.5",
    "react-router-dom": "4.3.1",
    "axios": "0.18.0"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "browserslist": [
    ">0.2%",
    "not dead",
    "not ie <= 11",
    "not op_mini all"
  ]
}

```

None of the solutions above have helped me. You cannot upgrade Jest because react-scripts comes with version 23.x so you are just adding on top of what react-scripts would already have. You cannot upgrade react-scripts so that it will have jest@24 because the latest version has jest@23.

Changing to v11.10.1 does not help either and within my Dockerfile I have tried changing the 'FROM' in my `Dockerfile` to `FROM node:10.15-alpine` and that has not helped.

When I tested it in this manner:

`docker run -it --rm -v $(PWD):$(PWD) -w $(PWD) node:10.15-alpine npm test`

it passed!

```
 PASS  src/App.test.js (10.163s)

  ✓ renders without crashing (5ms)

```

But it does not pass in TravisCI

This is my `Dockerfile` for my `client/src` directory:

```
FROM node:10.15-alpine as builder
WORKDIR '/app'
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

FROM nginx
EXPOSE 3000
COPY --from=builder /app/build /usr/share/nginx/html

```

I even tried changing my `.travis.yml` file to this:

`- docker run -it --rm -v myproject/react-test node:10.15-alpine npm test -- --coverage`,

when it was originally this:

```
script:
  - docker run myproject/react-test npm test -- --coverage

```

Absolutely nothing appears to be working here.

# Answer
You cannot rely on `FROM node:10.15-alpine` alone to fix this. I had to go with the fix from the facebook team. So if anyone else did not get a fix from modifying your `Dockerfile` to `node:10.15-alpine`, go to your `package.json` file and change react-scripts to the following facebook fix:

`"react-scripts": "3.0.0-next.b0cbf2ca"`

Then go ahead and remove your `node_modules/` folder via `rm -rf node_modules` and then run `npm install`, check your `jest-util` file, it should now have an output like this:

```
└─┬ react-scripts@3.0.0-next.b0cbf2ca
  ├─┬ babel-jest@24.5.0
  │ └─┬ @jest/transform@24.5.0
  │   ├─┬ jest-haste-map@24.5.0
  │   │ └── jest-util@24.5.0  deduped
  │   └── jest-util@24.5.0
  └─┬ jest@24.5.0
    └─┬ jest-cli@24.5.0
      ├─┬ @jest/core@24.5.0
      │ ├─┬ @jest/reporters@24.5.0
      │ │ └── jest-util@24.5.0  deduped
      │ ├─┬ jest-runner@24.5.0
      │ │ └── jest-util@24.5.0  deduped
      │ ├─┬ jest-runtime@24.5.0
      │ │ └── jest-util@24.5.0  deduped
      │ ├── jest-util@24.5.0  deduped
      │ └─┬ jest-watcher@24.5.0
      │   └── jest-util@24.5.0  deduped
      ├─┬ jest-config@24.5.0
      │ ├─┬ jest-environment-jsdom@24.5.0
      │ │ └── jest-util@24.5.0  deduped
      │ ├─┬ jest-environment-node@24.5.0
      │ │ └── jest-util@24.5.0  deduped
      │ ├─┬ jest-jasmine2@24.5.0
      │ │ ├─┬ jest-each@24.5.0
      │ │ │ └── jest-util@24.5.0  deduped
      │ │ └── jest-util@24.5.0  deduped
      │ └── jest-util@24.5.0  deduped
      └── jest-util@24.5.0  deduped

```

You should be good to run TravisCI build now. The issue is the react-scripts version `2.1.8` is conflicting with new version of Node. Suffered through this all day long, grateful to the facebook team for getting back to me.

For reference: https://github.com/facebook/create-react-app/issues/6475
> 0 votes

---
Tags: docker, dockerfile, travis-ci, node.js, alpine
---


# Question
Title: Any suggestion for a provider to deploy a first Dockerized application?
To conclude my Docker course, I would like to make my students deploying an app on some cloud provider. *A priori*, the deployment will be on a single host using `docker-compose` (i.e., no swarm, no kubernetes).

Which provider would you suggest knowing this is for students? I am looking forward to some free solution and the deployment needs to be seamless, ideally from the command line.

I've seen DigitalOcean provides a free trial with ssh access so that could do the trick. But I never worked with them, so I'm not sure they aren't hidden issues. Also, even for the free trial, they seem to require a credit card number, which may cause difficulties to some of my students. Any other idea?

# Answer
You can launch a t2.micro instance in AWS and use it free for the first year. Check for the RAM and disk space and keep your docker image and container within those limits. You can either use AWS ECR as image registry or Docker Hub.
> 2 votes

# Answer
First time users can obtain a free tier for a year with AWS, however, they will still ask for payment information if I am not mistaken. The nice thing about this solution is you can teach your students how to use Amazon Web Services such as Elasticbeanstalk, Elastic Compute Cloud (EC2) and these skills are valuable.

Whereas, using a vanilla Linux server through Digital Ocean or Linode can also be educational, it would be highly technical, meaning a lot of use of the terminal command line, setting up SSH creds, securing, hardening and optimizing a Linux server which the average beginner and lay person does not know how to do and you do not need to self-disclose, but if you do not know how to do this, then just go with Amazon Web Services as I suggest.

Having students playing around a Linux server without knowing security principles and practices is not right, but don't take my word for it, set up a Linux server for yourself as a test on DO or Linode and wait awhile, wait for Linode customer support to inform you about some repeated attempts at brute-force attack on your server.

It's not personal, these scripts are out there and they sniff out servers that are not well-secured and not having anything of value is not the issue, I imagine you want these students to learn well, so if the Principles of Least Privilege and securing, optimizing and hardening a Linux server is not in the scope of your course, go with AWS.

You can always show them how to shut down an EC2 instance and Elasticbeanstalk as part of the course.
> 1 votes

---
Tags: docker, docker-compose, cloud
---


# Question
Title: shell script to pass values properties file in java
I have a properties file that looks like this:

```
mysql.username=USERNAME
mysql.pass=PASS

```

I need to change `USERNAME` and `PASS` with variable values passed to shell script. I cannot use `sed` since that will work fine the first time to replace USERNAME and PASS with "values" but once they are replaced, sed will not find the variable names in the file the second time the script runs and thus an issue.

How can this be handled?

# Answer
> 1 votes
You can obtain old parameters from the properties file before using **sed**, e.g.

```
# get old parameters
$ export oldUsername=$(grep mysql.username $FILE | cut -d'=' -f2)
$ export oldPass=$(grep mysql.pass $FILE | cut -d'=' -f2)

# set new parameters
$ export newUsername=NEW_USERNAME
$ export newPass=NEW_PASS

# change parameters
$ sed -i "s/$oldUsername/$newUsername/g" $FILE
$ sed -i "s/$oldPass/$newPass/g" $FILE

```

# Answer
> 1 votes
You can use below.

```
[user@xyz ~]$ hh='mysql.username=USERNAME';echo $hh | awk -F"=" '{OFS=FS}{ $2="Mango"; print }'
mysql.username=Mango

```

# Answer
> 1 votes
You should regenerate this file from a template using your configuration management system of choice.

You could also write a shell script that uses a heredoc to do the same thing. But since we're in DevOps-land you really should be using your configuration management system for these things.

# Answer
> 0 votes
Maybe, this is something you can try - in sed they are known as back-references:

$1 - is the value passed for username

$2 - is the value passed for password

\1 captures the back reference within \\( and \\)

```
sed -i "s/\(mysql\.username=\).*/\1$1" propertiesfile
sed -i "s/\(mysql\.pass=\).*/\1$2" propertiesfile

```

---
Tags: shell-script, bash
---


title: What are immutable servers?

text:
# Question
Title: What are immutable servers?
There are some questions about ***immutable servers***, such as:

It seems obvious that it has to do with servers (that part I get). And just digesting the grammar of ***immutable***, I would think it has something to do with "not possible to *mute*". If that guess is close, I'd have no clue what exactly cannot be muted (and I doubt it has to do with soundcards or something ...).

**My questions**:

* What is actually a "immutable servers" (in the context of DevOps)?
* Why are they used?

# Answer
Immutability is a term often used in computer science circles, which generally boils down to "not possible to change after creation". It is typically used in reference to parallelism, concurrency, and thread safety.

The discussion of that topic is fascinating, but can generally be found elsewhere on Stack Overflow. I'm resisting the urge to dive into it here. The key concept is 'not possible to change after creation'.

Imagine if, on Amazon, you deploy a web service by baking it into a Machine Image (AMI - a pre-built instance you can repeatedly re-provision). It connects to a backend database via credentials it gets out of a registry on startup. It dumps logs into a logging tool like Splunk. For normal day-to-day operation, you have no reason to ssh into this box. If you need to scale up that service, you just create more instances of that AMI and adjust a load balancer. Spinning it down is simply the destruction of instances and load balancers.

For the day-to-day operation, this box has *no reason to change*. We can just fire up more off of the AMI.

What happens when you need to provide an OS-level security patch? This is when you have a decision to make... do you bake a new AMI with the patch installed and redeploy all running instances, or do you ssh into existing images and update the patch? There are plenty of people who would just ssh in. The adherents of 'immutable architecture' just yelled at me for even suggesting such a thing is possible.

Immutabilists (if there is such a word) advocate baking the new ami. They advocate removing all reason to ssh into a machine ever. They advocate that any specific machine configuration should happen on the startup of that machine by pulling config details out of a repository. This is the ultimate expression of 'cattle, not pets'.

Immutable architecture is specifically about machine configurations that *have no reason to change after the creation of the machine image*. If something needs to change, bake a new instance image, shut down the old, bring up the new.
> 22 votes

# Answer
Immutable servers are servers on which no changes can be made (other than updates and security patches ideally). Instead of changing the software on the server, you spool up a new server with the desired software and then terminate the older one.

This concept helps to ensure that your test, development, and QA server are all identical, which is important for multiple reasons out of the scope of this question. Another benefit of immutable servers is the ability to rollback the application onto an older server. For example, I need to change K on production server 1, so I spool up server 2 and change K. Now after 10 minutes, I notice that K broke something with my application, rather than having to fix it right away which could take hours and potentially cause downtime for my customers, I redirect the traffic back to server 1, while I figure out what is wrong with 2.
> 10 votes

# Answer
Cloud technologies shifted the frontier between hardware and software so that many technical operations formerly exclusive citizen of the hardware world are also subjects of the software realm. Shared computing environments might be as old as computers themselves1 but cloud technologies could popularise them by offering convenient and familiar metaphors to interact with them: cloud users reserve an *instance,* a complete computer or a mimic, whereas older shared computing environments have all possible set of unwieldy limitations and “your program have to be uploaded on that FTP server, will run in environment X (usually with 10y old version of whatever software you want to use), for at most 60 minutes” could sound familiar to former or actual users of computing centres.

The practical consequence of this shift is that deployment procedures can now be represented by *software artefacts.* (Deployment procedures are the instructions telling how to setup an infrastructure, with databases, web-servers or whatever belongs to this infrastructure, together with the network where they run on.) Geared with these new lenses, manual maintenance of servers pretty much looks like manual patching of production code – which is only in very rare occasions a desirable thing. Manual maintenance is susceptible to introduce discrepancies between the systems actually running in production and the code describing these systems, which in turns mean irreproducible behaviour and impossible bug analysis, dual bug fixing, and other calamities.

The *immutable server pattern* is just the transposition for cloud operations of the above mantra, according to which we should avoid manual maintenance of running programs. Instead of manually configuring severs, the *immutable server pattern* recommends to automatise this configuration.

## Implementation flavours

While the general idea of the *immutable server pattern* is quite clear, there is a lot of implementation nuances. For instance, some approaches suggest to not update servers at all but to systematically *replace* servers instead. This is because updating yields situation where a deployment consists of servers having been started at several distinct times and having gone through several, distinct, updating processes which implies an inhomogeneous set of servers and can lead to subtle differences in how servers handle their jobs. A second popular variation point is the discipline regarding remote access to the servers. Some like to disable completely remote administrative access to servers, in order to guarantee that manual maintenance never happens.

## History note

To the best of my knowledge, the term “immutable server” has been popularised by Kief Morris but the idea itself is much older. In 1999 FreeBSD jails already popularised the idea of fully automatising the configuration of disposable computing environments, this is how I started to implement the “immutable server” pattern many years before I heard this name to describe this technique.

Immutability, in the guise of physical immutability based on CD-ROMS, has also been a popular measure to manufacture trusted computing systems. This is not to be mistaken with the immutable server pattern.

---

1If we don't count automatic loom tables or roller organs as computers.
> 10 votes

# Answer
The best explanation can be found (as always) on Martin Fowler's bliki article on Immutable Servers.

A server, be it hardware or a virtual server in the cloud, usually has an operating system and application running on it.

Often application, and components of the operating system, require configuration and require changes to be applied. For example security patches, deployment of new versions of the application and configuration changes.

When you consider that any change is a *mutation* on the state of the server, the term `immutable` starts to make more sense. It means that no *mutations* are allowed on such a server.

It is often the case, when people are involved in changing the state of the server - be it a deployment of a version, or configuration change, or a security path. The result is a server that is no longer working as expected. For example, the application might not run now because of misconfiguration, etc.

This is why a practice for creating *immutable* servers is established. With *immutable* servers, an **image** of a server is created with all the configuration, patches, application versions bundled in. Then that server **image** can be used to create servers in various environments.

The first environment where such an **image** is used, would be an environment where the image can be tested to work. Any abnormalities are detected, and only then such an image can be **promoted** to a production environment to replace the servers there with the new version (which is known to work well).

Once the process of creating the images and promoting the images is automated, you get a very failure-proof process that involves very little human effort and very low chance to introduce failure into your service.

Often immutable servers don't even include any way to "enter" them, such as for example the ssh server is missing. In this case it is also often the case that all the metrology of a server (metrics, logs) is shipped to systems outside such as a metrics database or log aggregation service.

With containers (see: Docker) there is also a process to create images, and then spawn these into running containers. These are quite often replaced by new containers based on updated images, and are never mutated. Meaning that no human enters into the container to "fix something" by introducing a change.
> 7 votes

# Answer
Let's start with the inverse, what is a mutable server?

Traditionally, a mutable server infrastructure is one that is continuously modified and updated in place. You can secure shell into it, upgrade packages, configure it, install services and deploy new code to it. This is what makes it mutable, you can mutate or modify it.

An immutable infrastructure is another infrastructure paradigm in which servers are never modified after they're deployed. If something needs to be updated, fixed, or modified in any way, new servers built from a common image with the appropriate changes are provisioned to replace the old ones. After they're validated, they're put into use and the old ones are decommissioned.

**Why are they used?** The benefits of an immutable infrastructure is more consistency and reliability in your infrastructure and a simpler, more predictable deployment process and it mitigates common server issues in mutable infrastructure, such as downtime from the server crashing or whatever.

But you have to know how to provision it efficiently via comprehensive deployment automations and fast server provisioning.

Imagine you are mining bitcoin, you would not want any downtime if your server crashed, you would need it back up as fast as possible, so an immutable infrastructure is supposed to be the solution.
> 0 votes

---
Tags: terminology, immutable-servers
---


# Question
Title: Which option do I select for Security Group Source?
I am developing my Security Group for a VPC that has my Elasticbeanstalk, RDS and ElastiCache services and I am at this dashboard:

Under **Source**, it used to be that you could select `sg-0x12345-my-application`, but now it only gives you the option of **Custom**, **Anywhere** or **MyIP** and I am not sure which one is the equivalent to selecting the security group for the architecture I am building this SG for.

# Answer
> 1 votes
Use **Custom** and then start typing `sg-...` and it should pop up a list of available groups.

---
Tags: amazon-web-services, aws-vpc
---


# Question
Title: What are some effective questions to ask someone who is considering me as their DevOps person?
So these days, DevOps has been reduced to the guy who uses Puppet, tick, he uses Jenkins, tick and so on.

What effective questions can I ask to ensure the client and I would be on the same page as to what I would be doing as opposed to just looking for the guy who does Puppet/Jenkins and/or Kibana/Logstash, etcetera.

In other words, on paper they will not see "DevOps" anywhere. I do have some "DevOps" accomplishments on paper, the work that was done, but my title was still that of a Developer. To many of you, that makes perfect sense, but to the business world, its like if you don't have "customer service" as a past title, then you don't have "customer service" experience. Your resume wont appear on Indeed for the person looking for that.

How do most of you navigate those waters in terms of a presentation? What do you say?

# Answer
In my opinion since the DevOps culture is derived from, or you could say appeared because of, the Agile software development methods

* I would ask if the company is following any agile software methods or else you would be just the release guy
* Also I would ask how I will be working as part of the dev team like I will be assigned to one project team or I will be working with all the teams
* Also it would be great to know the current situation like they are currently facing urgent problem and need fix now , what's their current stack , and also ask about their current workflows in git and in development and try to find a way to solve the issue to make everything go smoothly
* Also what really appears on paper is the workflows like git workflows, how often you release cause automating parts like delivery, and integrations,......etc really means less time and better quality and that will appears on paper even for the business guys

But at the end if the day every company is different than any other and every situation is different than the other so it's all back to your judgement to be comfortable in your daily job.
> 5 votes

# Answer
* Ask if they track DevOps time to know the amount of work
* Ask how many external services do they have and if you need to manage them
* Ask how many technologies do they own and use daily and what you need to manage
* Ask how big is their server infrastructure and how do they monitor it
* Ask who teaches people how to work with `ssh` and `git rebase`
* Ask if they need you to optimize DB queries

Ask them to cross out any two things from the menu above. )
> 2 votes

---
Tags: job-role
---


# Question
Title: How can I access the console of a booting EC2 instance in AWS?
I'm new to AWS and am looking for a way to access my EC2's console so I can triage issues such:

* boot to single user mode
* view console output as system boots
* gain console access to debug GRUB issues

# Answer
> 2 votes
### Background

When using cloud services such as AWS or Azure your ability to access the console of booting instances is typically restricted to a read-only type of interaction.

AWS does provide tools, so you just need to adjust your approach, if you're expecting to drop to single user mode or watch a booting system on a console.

For example, in the EC2 services area of AWS you can select a EC2 instance and then under the actions menu select either:

* Get System Log
* Get Instance Screenshot

### Example

**Step 1: Screenshot of actions menu**  **Step 2: Screenshot of "System Log"**  **Step 3: Screenshot of "instance's console"**

---
Tags: amazon-web-services, amazon-ec2, linux
---


title: Rancher, Load Balancing and own domain

text:
# Question
Title: Rancher, Load Balancing and own domain
I have a question about rancher. I'm running my rancher on aws. I have created a new cluster with two nodes (workers) and I have deployed my docker images. Now I wanted to add Load Balancer, but I don't want to use xip.io domain but my own. I added my domain to route 53 and I wanted to make redirection from api.mydomain.com to Load Balancer. So, I added in route 53 new record and I used IP of my ec2 machine (I checked where the load balancer has been deployed in rancher)

The question is: What if I will want to change my nodes? My domain will stop working because I'm using the ip of ec2 machine. How should I point dns to my LB correctly (because I'm thinking that using the ip of ec2 machine is a not correct solution).

# Answer
> 1 votes
Your first step is to setup and configure the Route53 service from the rancher catalog.

After that, the load-balancer will automatically update its DNS in Route53.

---
Tags: amazon-web-services, amazon-ec2, dns, rancher
---


# Question
Title: Triggering specific pipeline builds for monorepos in Jenkins
I'm in the process of converting multiple repositories into a single repository, our CI tool of choice is Jenkins due to the conversion of multiple repository structures into a single one 2 main issues have arisen.

1. Build/test times have increased significantly as all the builds/tests have to be run for every single commit. This is partially alleviated by using a build tool, in our case we have gone with using Buck.
2. After all the tests associated with the committed code are run, I have a deployment Jenkinsfile for each project. How will I be able to only trigger the Jenkinsfiles for projects that need to be re-deployed? And if I am able to do so, is this a correct practice?

# Answer
> 5 votes
1. Get a list of changed files and use that to determine which tests to run.
2. Load external Groovy scripts at run time in order to run your deploys.

# Answer
> 15 votes
You can use the "when" block combined with the built in "changeset" condition to conditionally run only certain stages of your monorepo's pipeline. From the when.changeset documentation:

changeset- Executes the stage if the build’s SCM changeset contains one or more files matching the given string or glob. Example: when { changeset "\**/\*.js" }

Here is an example Jenkinsfile using this strategy:

```
pipeline {
    agent any
    stages {
        stage('build matchengine') {
            when {
                changeset "**/matchengine/*.*"
            }
            steps {
                echo 'building match engine'
            }
        }
        stage('build posttrade') {
            when {
                changeset "**/posttrade/*.*"
            }
            steps {
                echo 'building post trade'
            }
        }
    }
}

```

, applicable to the monorepo project structure shown below:

```
 .(my-project)
   |-- Jenkinsfile
   |-- matchengine
   |-- posttrade
   |-- serverless
   |-- ui

```

This strategy won't scale past small codebases because it would be hard to keep track of which modules depend one each other. You would be better off using a build system like Bazel. Your CI job would simply issue a bazel build //... (build everything), and Bazel would calculate what actually needs to be built, and what needs to be tested. Further, there even exist bazel rules such as rules\_docker and rules\_k8s which can calculate which of your containers need to be rebuilt and pushed to a container registry, and which of your applications need to be redeployed to Kubernetes.

---
Tags: jenkins, jenkins-pipeline, jenkinsfile
---


# Question
Title: How to structure a IaC for production, and development?
We have a typical multi layered web application: a balancer, 2 web server 2 db server.

I feel we strongly need to start using a kind of Infrastructure As Code in order to replicate easily environments, testing infrastructure updates, control production servers.

I've never done that and I'm struggling to understand the workflow. I'm thinking something like this:

* create locally my machines with docker and Dockerfiles.
* use terraform to setup locally the infrastructure provided by docker (or docker-compose?).
* reuse in some way the Dockerfiles to provide the production or staging machine (we don't use Docker in production, but rather AWS with EC2/AMI and RDS).
* use ansible to deploy the application.

I'm not sure this is the way. Or maybe it's too complex

# Answer
Ok so I understand that you are in AWS and Docker already and Terraform is something you want to bring into picture for IaaC. and Yes, docker for production. Now, let's start with environment: Assume you have three environments, Dev, Test and Prod. So you create three folders, Dev, Test and Prod which contain infra code for three environments. Now, I don't understand what you mean by infrastructure provided by docker but docker will contain your web servers and web application. Number of containers will depend on how large or small your application is and are you in micro services architecture. So what Terraform does for you is creating almost everything: Right from network structure(VPC, subnets, NACLs, gateways etc), autoscaling groups(I prefer this as you may want to use docker orchestration), security groups, IAM roles, policies to RDS and ECS etc.

So you can tag them in your code as per their environment and you create each of these components using Terraform modules.

So now you have Terraform code which creates infrastructure for you. Store your state file in S3 because you want consistency in your infrastructure state. Keep your database state file separate from other state files. You may want to have separate state files for your network, security groups, RDS, IAM, Cloudwatch etc.

Now comes the deployment part: Since you are in Docker, why don't you use AWS ECS? It will be easy deployment (Almost zero downtime) and orchestration will be managed by ECS itself. So now even deployment you can do using Terraform. Maintain a separate state file for this too.

You can create separate docker images for dev, test and production during your CI. If you do not have any docker tagging strategy, you may use $BUILD\_NUMBER:$ENV for now. One of the purpose of using docker is that you don't need to care about where you want to run the container so identical docker images for Dev, Test and Production is almost always ok with some configuration changes.

You do not create anything locally. Use CI/CD tools such as combo of Jenkins and Git which triggers everything.
> 1 votes

# Answer
Here two parts: use IaC tools like Terraform to create environments and use Docker to deploy applications.

1) You can use Terraform with workspaces to make production and development. Maybe use Packer to prepare AMI images to reduce time for building.

2) Decide what CI/CD pipeline you will use to deploy apps. And first of all here you should know what orchestration tool you will use for Docker containers - compose, swarm, nomad, kubernetes.
> 1 votes

# Answer
If I understand your need:

* Need Infrastructure as Code.
* Configuration management.

Terraform is a great tool for creating your infrastructure. It has API support for AWS, GCP and almost all the cloud providers. Now that your infrastructure is ready, you need to configure the same using tools like (CHEF, Ansible or Puppet). I have personally bootstrapped the nodes created by Terraform to CHEF and have run cookbooks.
> 0 votes

---
Tags: docker, terraform, infrastructure-as-code
---