title: Branching model for nightly deploys

text:
# Question
Title: Branching model for nightly deploys
I'm a lead developer for a small B2B SaaS company, using Django and AWS. We currently run biweekly deploys after hours with a mostly-automated custom Fabric-powered tool.

We're currently exploring options for moving to fully-automated nightly deploys, but want to move to a different branching model to support this.

Right now, topics are branched from dev and merged to dev, a long-running branch which is merged wholesale with --no-ff into master during the biweekly prod deployment process. This necessitates a feature freeze on release days, to ensure that broken code isn't merged right before a release, and isn't really a great solution.

My current plan is to move to a more branch-oriented workflow, similar to Gitworkflow: https://github.com/rocketraman/gitworkflow. This would allow us to merge feature/bug branches individually to dev, then only merge to master the branches (corresponding to Jira issues) that have passed manual QA.

Is this a good approach?

In my mind, there are a few potential open questions, like how to handle issues/branches which have failed QA, and should be removed from the dev branch/environment. I suppose that instead of reverting commits, we could then "refresh" the dev environment by overwriting it with master, and re-merging all branches currently undergoing QA...

# Answer
> 2 votes
You're bringing up a big pain point - and there are 2 camps here, people who do GitFlow and people who prefer other approaches (with TBD being most popular).

Personally, TBD with release branches is something I would always prefer, but you can find lots of other people who would tell you GitFlow is better - so you'd have to decide for yourself.

In your case TBD would work as following - you keep committing to your master, however before release time you cut a release branch out of master. Once you do that, you don't have to code freeze master and your developers can keep working there.

Some materials for research: On Gitflow - https://nvie.com/posts/a-successful-git-branching-model/

On TBD - https://trunkbaseddevelopment.com/ (especially check "Scaled Trunk-Based Development" section)

Critics of Gitflow (note that myself I'm biased towards TBD) -

1. https://georgestocker.com/2020/03/04/please-stop-recommending-git-flow/
2. https://medium.com/@mattia.battiston/why-i-love-trunk-based-development-641fcf0b94a0

---
Tags: git, deployment, continuous-delivery
---


# Question
Title: Update ECS task definition with new image from ECR
I have an ECS cluster/service/task definition using an image from my ECR repository.

Let's say I update the image with a new version, will ECS pick the changes automatically?

1. Do I need to modify the task definition?
2. Do I need to somehow reload/restart the task(s)?

My goal is to automate the deployment to ECS. I'm not sure if using CodeBuild to build and push the new image to ECR is enough, or if I need something else (codepipeline?) to deploy changes to ECS.

Note: task definition is using "latest" image tag, new images update that tag in ECR.

# Answer
Options are:

1. Use CodeBuild to push the new image. Make sure the task definition is using the "latest" tag. You'll need to force the deployment of the task definition to pick the new image.
2. Use CodePipeline to update ECS. It will automatically generate a new task definition revision with the new image and deploy it.
> 5 votes

# Answer
If task definition is using "latest" as image tag in container definition,to update ecs service in order to pull new image from ECR with "latest" tag. You can simply do Force new deployment aws ecs update-service --cluster --service --force-new-deployment --profile

All though using "latest" tag for deployment is not good practice
> 3 votes

---
Tags: docker, amazon-ecs, docker-registry
---


# Question
Title: Make TeamCity see test results in real time using Maven, JUnit 4 and Surefire
So we have a TeamCity with numerous JUnit 4 test suites builds configured.

The problem: Tests tab is only populated after build is complete. If build crashes, tests tab is not populated, even with tests which completed before crash.

The reason for that is Surefire reporting the following to teamcity:

```
##teamcity[importData tc:tags='tc:internal' type='surefire' path='.../target/surefire-reports/TEST-*.xml' whenNoDataPublished='nothing' logAsInternal='true']

```

So TeamCity cannot know the state of tests until suite is done and XML file is written.

Now, TeamCity supports real-time tests reporting with messages such as

```
##teamcity[testStarted name='MyTest.test1']
##teamcity[testFailed name='MyTest.test1' message='failure message' details='message and stack trace']
##teamcity[testFinished name='MyTest.test1']

```

However, Surefire (the framework responsible for running JUnit tests in Maven) does not output such messages by default.

So it seems that I have three choices if I want tests to be reported in real-time:

* Configure a RunListener for JUnit/Surefire to output these messages for TeamCity. Obvious problem here is that I am reinventing the wheel here. I'm also not sure that my reporting of tests will closely match Surefire's reporting of tests in XML file, which may lead to glitches and duplication of tests.
* Change my tests to emit these messages. Easily doable since I have a common superclass for almost all tests, but reinventing the wheel is still there, as well as mismatch with XML.
* Find a way to either configure Surefire to output these messages, or make TeamCity talk to SureFire to enable their output. I recognize that Surefire is hit-or-miss thing, but this functionality is so popular I expect it has *some* solution.

Please help me choosing between these options. I have tried googling, the results are very poor.

# Answer
> 1 votes
So I have choosed implementing my own RunListener. I added a compile,test dependency on it to all my other modules and hooked it up in maven surefire plugin configuration. See also https://stackoverflow.com/questions/61206966/surefire-only-reports-first-test-suite-from-module-to-runlistener

---
Tags: maven, teamcity
---


# Question
Title: How to sync two directories on same host using Ansible?
I am using the below playbook for mounting partitions on another EBS volumes while provisioning instance on AWS

```
    ---
    - name: Mounting necessary partitions
      hosts: localhost
      become: yes
      become_user: root

      tasks:

        - name: Ansible formating partitions.
          command: "{{ item }}"
          loop:
            - mkswap -f {{ ebs_swap }}
            - mkfs.xfs -f {{ ebs_home }}
            - mkfs.xfs -f {{ ebs_var }}
            - mkfs.xfs -f {{ ebs_tmp }}
            - mkfs.xfs -f {{ ebs_app }}
            - mv -f /home /home_old
            - mv -f /var /var_old

        - name: Dispaly uuid & store in variable
          command: blkid -s UUID -o value {{ ebs_swap }}
          register: uuid_swap

        - name: Dispaly uuid & store in variable
          command: blkid -s UUID -o value {{ ebs_home }}
          register: uuid_home

        - name: Dispaly uuid & store in variable
          command: blkid -s UUID -o value {{ ebs_var}}
          register: uuid_var

        - name: Dispaly uuid & store in variable
          command: blkid -s UUID -o value {{ ebs_tmp }}
          register: uuid_tmp

        - name: Dispaly uuid & store in variable
          command: blkid -s UUID -o value {{ ebs_app }}
          register: uuid_app

        - name: Creates directory
          file:
            path: "{{ item }}"
            state: directory
          with_items:
            - /home
            - /var
            - /tmp
            - /app

        - name: Add the below lines
          blockinfile:
            path: /etc/fstab
            state: present
            block: |
              UUID={{ uuid_swap.stdout }}   swap      swap defaults                         0   0
              UUID={{ uuid_home.stdout }}   /home     xfs  defaults,nodev                   0   0
              UUID={{ uuid_var.stdout }}    /var      xfs  defaults,noexec,nosuid,nodev     0   0
              UUID={{ uuid_tmp.stdout }}    /tmp      xfs  defaults,noexec,nosuid,nodev     0   0
              UUID={{ uuid_app.stdout }}    /app      xfs  defaults                         0   0

        - name: Mounting disks permanently
          command: "{{ item }}"
          loop:
            - swapon -a
            - mount -a

        - name: Copy multiple Directories
          copy:
            src: "{{ item.src }}"
            dest: "{{ item.dest }}"
            mode: "{{ item.mode }}"
          with_items:
             - { src: '/home_old/',dest: '/home/',mode: preserve}
             - { src: '/var_old/',dest: '/var/',mode: preserve}

```

I have tried multiple ways to copy the data back to newly mounted EBS volumes at task name `Copying /home data on new EBS`.

I have tried using `copy` `synchronization` & `rsync` modules. I know using `cp` is not recommended option but I can not see any other option related to syncing the data between to directories with preserving permissions.

But when I do it manually it works perfectly.

I am mounting these partitions on another EBS is just coz of CIS hardening steps includes it.

I have followed a couple of blogs already. such as 1. one 2. two

Can anyone help in solving this? This is very urgent.

> ERROR: `failed: [localhost] (item={u'dest': u'/var/', u'src': u'/var_old/'}) => {"ansible_loop_var": "item", "changed": false, "item": {"dest": "/var/", "src": "/var_old/"}, "msg": "could not find src=/run/acpid.socket, Could not find or access '/run/acpid.socket' on the Ansible Controller.\nIf you are using a module and expect the file to exist on the remote, see the remote_src option"}`

# Answer
> 3 votes
The copy module copies a file from the local or remote machine to a location on the remote machine.

In order to copy the file from the remote machine itself, set `remote_src` to `yes`.

```
- name: Copy multiple Directories
          copy:
            src: "{{ item.src }}"
            dest: "{{ item.dest }}"
            mode: "{{ item.mode }}"
            remote_src: yes
          with_items:
             - { src: '/home_old/',dest: '/home/',mode: preserve}
             - { src: '/var_old/',dest: '/var/',mode: preserve}

```

# Answer
> 0 votes
I have used below code to resolve the issue.

```
    - name: Copy var directory
      shell: |
        cp -rpf /home_old/* /home
        cp -rpf /var_old/* /var
      args:
        executable: /bin/bash

```

Thanks.

---
Tags: ansible, linux
---


# Question
Title: How to run multiple commands with command module in Ansible
I want to run couple of commands in ansible playbook I am trying below:

```
 - name: Running multiple cmds
   command:
    - |
      cmd2
      cmd2
      cmd3
      cmd4

```

But i am getting an error on this task while running above code.

**Update**: I am trying to use below commands using command module but getting an error:

```
- name: install pexpect using pip
  shell: /bin/bash -c "pip install pexpect"

- name: Join system to AD
  expect:
    command: "{{ item }}"
    loop:
      - source /etc/os-release
      - realm join --membership-software=adcli --user=username@EXAMPLE.COM --computer-ou="OU={{ env }},OU={{ account }},OU=XXXX,OU=XXXXXX,DC=XXXXXXX,DC=XXXXXXX" --os-name="$PRETTY_NAME" --os-version="$VERSION" <DCNAME>
    responses:
        Password for *: "{{ username | b64decode }}"

```

Error:

```
TASK [adjoin : Join system to AD] ***********************************************************************************************************************************************************
fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'item' is undefined\n\nThe error appears to be in '/tmp/ansiblepull/playbooks/roles/adjoin/tasks/main.yml': line 58, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- name: Join system to AD\n  ^ here\n"}

```

Can anyone help me in solving this.

I am getting an error while syntax-check as well.

# Answer
I have fixed updated error with the below module:

```
- name: Join system to AD
  expect:
    command: /bin/bash -c "realm join --membership-software=adcli --user=username@EXAMPLE.COM --computer-ou="OU={{ xxx }},OU={{ xxxx }},OU=xxxx,OU=xxxxx,DC=xxxxxxxx,DC=xxxx" --os-name={{ ansible_distribution }} --os-version={{ ansible_distribution_version }} DCNAME"
    responses:
        Password for *: "{{ join_user_pass | b64decode }}"

```
> 0 votes

# Answer
The Ansible documentation states that the command module doesn't get a shell

> The command(s) will not be processed through the shell

The `command` module takes the command as an argument, so you can't have list as you've written there. You could do the same thing in a `loop:` with `command: {{ item }}` :

```
- name: "Run {{ item }}"
  command: "{{ item }}"
  loop:
    - cmd2
    - cmd2
    - cmd3

```

You could also have several `command:` tasks instead.

However, this is generally considered bad practice (E.g. E303 from Ansible Lint rules) because it tends to break idempotency. It would be better to decompose those commands into something that uses Ansible modules.
> 4 votes

---
Tags: ansible
---


# Question
Title: How to mark build success when one of the stages is aborted?
I've a pipeline with stages where one of the stage, intermittently takes longer than expectation and hence using `timeout` to abort it. But if the stage is aborted, build also marked as aborted. Following is the code for pipeline -

```
pipeline {
    agent any

    stages {

        stage('First') {
            options {
                timeout(time: 10, unit: 'SECONDS')
            }
            steps {
                script {

                    catchError(buildResult: 'SUCCESS') {
                        echo "Executing stage I"
                        sleep 12
                    }

                }
            }
        }

        stage('Second') {
            steps {
                script {
                    echo "Executing stage II"
                }
            }
        }
    }
}

```

Even though the stage is marked as `Aborted`, I want to mark build as `Success`. Can you please help how I can achieve this?

# Answer
> 2 votes
I answered that question stackoveflow and I'll post the answer here:

For a Declarative pipeline (not a scripted) you would do something like this

```
stage('Foo') {
      steps {
            script {
                env.PROCEED_TO_DEPLOY = 1
                try {
                    timeout(time: 2, unit: 'MINUTES') {
                        // ...
                    }
                } catch (err) {
                    env.PROCEED_TO_DEPLOY = 0
                }
            }
      }
  }
  stage('Bar') {
    when {
        expression {
            env.PROCEED_TO_DEPLOY == 1
        }
    }
    //rest of your pipeline

```

stage "Bar" would be skipped but as for the rest of the stages the job will be marked as passed (assuming nothing wrong happened before).

As for your particular use-case, the trick is to use a try/catch block.

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


title: When does Jenkins clean up old builds?

text:
# Question
Title: When does Jenkins clean up old builds?
I have existing Jenkins (2.90) jobs that are taking up disk space. When I enable the "Discard Old Builds" option I don't see any cleanup going on in the folder on the builds older than 7 days.

When does Jenkins do this cleanup? Or does it only apply for new builds after I apply the setting?

# Answer
Per the Jenkins documentation:

> Cleanup per project/job is performed after that job runs.
>
> As of v2.221, cleanup will also periodically run using the new Global Build Discarders (even if a job has not recently been run).

Source.
> 5 votes

---
Tags: jenkins
---


# Question
Title: Referencing locally built Docker images in Terraform
Is it possible to use docker images in Terraform that are **not hosted in a registry** but in the local Docker storage?

I'd like to have a resource like the following where **no pull** is performed on the image if it exists locally.

```
resource "docker_container" "my_service" {
  image = "my_locally_built_image_name"
  name  = "my-service"
}

```

# Answer
> 3 votes
Yes, As we write terraform template is correct. When you use terraform apply it will check local docker image list if it doesn't exit it will go to find registry as you define docker image.

If you don't want a pull image from the internet you can try the below steps. But at least you should have a base docker image of any Linux distribution.

1. Create a Dockerfile.
2. Build Dockerfile as below command

`# docker build -t image_name -f Dockerfile`

3. Define the docker image as a template

`resource "docker_container" "my_service" {
 image = "image_name"
 name = "my-service"
}`

4. By **terraform init** install terraform module and apply the terraform template.

`# terraform init`

`# terraform apply -auto-approve`

---
Tags: docker, terraform, docker-registry
---


# Question
Title: What can I use to forward a conection to port 3006 on the bastion to an RDS database?
Forwarding a port 3006 database connection from a bastion server to a RDS database?

Trying to find the answer online I came across the term Proxy jump but can't find anything on proxy jump for 3006 to send a 3006 mysql conection to the bastion on port 3006 to an RDS?

# Answer
> 1 votes
***It is possible on the Linux(Unix) bastion host.***

Step-1: First ssh to the bastion host. *eg. 16.23.14.20 is the bastion host.*

```
# ssh root@16.23.14.20

```

Step-2: Create port tunneling by using the below command. eg. *The RDS IP is 172.16.13.10*

```
# ssh -L  3006:172.16.13.10:3006 localhost

```

Verify using netstat command.

```
netstat -ntulp | grep 3006

```

Note: If netstat command not available. Using `sudo apt install -y net-tools` or `sudo yum install -y net-tools`

---
Tags: databases, ports
---


# Question
Title: Is there a book only about Ansible (without touching Vagrant, VirtualBox, Docker and virtualization stuff)?
I need a book only about Ansible (without touching Vagrant, VirtualBox, Docker and other above-shell stuff).

About 6 months ago I tried reading the Ansible docs but these were totally un-understandable to me so I bought a good book by Jeff Geerling named "Ansible for DevOps" which is aimed of course for DevOps and thus includes extensive elaboration on software like Vagrant (OS-level virtualization-management tool), VirtualBox (OS-virtualization tool that is managed with Vagrant) and if I'm not wrong Jeff also touches Docker there, but this is not what I seek and had hard time understanding much because I had no DevOps background at the time besides some Bash.

I usually work with IaaS hosting services in which I can't even utilize Vagrant and VirtualBox and have no usage in Docker (I do well with Bash and some Bash extensions like Composer, Drush for Drupal and so forth which make Docker redundant for the projects I personally work on).

Is there a book that teaches Ansible but focuses only on Ansible, say, something that does general introduction to YAML, then to creating and playing Ansible playbooks on Linux environments (native/WSL)? Some kind of "Ansible for web developers" or "Ansible for general audience"?

# Answer
I would highly recommend looking at this tutorial by digital ocean. How to install and configure Ansible on Ubuntu.

Although this tutorial is not a book, I had a similar situation with the ansible docs and trying to understand them when I first got started. This tutorial will provide an in depth hands on experience for getting started with ansible.
> 1 votes

# Answer
I used the O'Reilly Ansible book: "Ansible: Up and Running, 2nd Edition" to learn Ansible and found it well-paced and helpful. It suggests using Vagrant to work with a virtual machine (VM) on your normal desktop/laptop to practise what you've learned, an approach I find very helpful - including now, since this is also a great way to prototype Ansible playbooks before deploying them.

Vagrant is also the tool advocated by Michael Heap in his "Ansible from Beginner to Pro", which is a bit faster-paced. Published in 2016 it won't have some of the newer Ansible features.

PacktPub have several Ansible books, so one of those may suit, and finally you've found LeanPub's "Ansible for DevOps" by Jeff Geerling already. (Update: Jeff Geerling now has several 1-hour Ansible videos on YouTube)

I hope that helps.

PS: re. your wish to avoid Vagrant, Virtualbox etc - I suggest that you consider these as useful tools to help you on your Ansible journey: You don't need to know much about them atall (sufficient info is given in the books mentioned), but they make for a really helpful way of quickly testing and prototyping your Ansible work - particularly since you can create and destroy them at will - so it's easy to recover if you mess up badly, and easy to test a playbook on several different distros at once. If you really don't like the Vagrant/Virtualbox aspect, use a spare Linux machine, be that on your local network or out there on the 'net.
> 1 votes

# Answer
**TL;DR** blogs and videos are for the impatient. Books focus on mastery. Mastering Ansible means setting up a local lab for testing full repeatable automation so you can confidential push out changes continously. That is why the book "Ansible for Devops" covers local lab setup with vagrant.

**Long Answer:**

To the specific question is their a simplier book? Why would there be as blogs and videos will cover the "5 minute guide". Blogs or videos take hours or days of effort but books take months or years. The famous "for dummies" series breaks the mold but most technology books are going to be about mastery. As an "IT veteran" I had until recently overlooked how important videos are in learning new IT. Book publishers are having to adapt to the streaming generation and introductory books are going the way of the dodo.

The rest of this answer says why Ansible for Devops has early chapters on setting up a vagrant lab locally for testing.

Ansible is an agentless tool that runs commands in parallel over ssh. That's very different from many other tools that have a client-server-agent model where you have to install an agent on every server you deploy onto. This means that as long as your IaaS has ssh access, and they all do, you can run Ansible.

What is unique to every IaaS is how the networking is done or how hosts are created. Ansible starts after that assuming you have networking to your hosts and ssh access to those hosts. The Ansible for Devops book doesn't and shouldnt have a section on how to setup a test env on every IaaS provider. It focuses on setting up a test env on your local laptop. Not because that teaches about IaaS it's a load of new skills you need to make your laptop "an IaaS provider". It is because without that it's unlikely readers of the book are going to be able to master Ansible. Would you want to try to master a programming language that doesn’t run on your laptop?

If you work on physical or virtual machines with Ansible at a bank they might not let you run vagrant or Docker locally or even have admin rights to your laptop or root access on VMs. Mastering Ansible in those situations is really hard. You only have a few test boxes and you have to run the playbooks hundred of times on them to debug. How can you be sure your finished playbook will work first time on production boxes that you cannot access until go-live weekend when it must all work first time? You cannot. Why? Because your last test run on you test hosts might only have worked because of some setting you changes on those hosts weeks ago that you forgot to put into the playbooks.

People might ask "what's that to do with me as I don't have those issues”. The point is that if you can run vagrant on your laptop and you can rapidly test and experiment you can learn faster. You can also delete it all, and set it up from scratch, as final testing of your playbooks. That doesn't mean it will work first time on your IaaS if your ssh access to hosts and networking isn't set up but once they are you will be flying.

Mastering anything in the devops space isn't about "I finally got it working" its about "I can automate this to work first time in live and I can constantly improve it". That is why no book called "Ansible for Devops" would be worth buying if it didn't show you how to locally test against a multi server laboratory on your laptop.

I strongly recommend that people invest their time in setting up a lab on their laptop. It will save you weeks or months over a relatively short time frame. It's really annoying when your laptop has several different labs setup that get slightly conflicting software versions you have to debug but those few hours of extreme frustration pay back fast.
> 0 votes

---
Tags: ansible, learning
---


# Question
Title: How comes a GitLab CI/CD job cant' find its artifacts?
In the Open Source ventilator project, we aim to provide those who focus on testing with a ready-to-go flash file for the Arduino controller board.

While the binaries seem to be there, for some reason the CI job can't pickup the artifacts.

What is happening:

* a CI/CD pipeline creates two files which can be listed using `find`
* in the next step, this pipeline reports it can't find these artifacts. It says, "no matching files/no files to upload".

What's the error and how to fix/troubleshoot? Why does this job end up as successful?

CI job definition:

```
compile:
  stage: build
  tags:
    - docker
  script:
    -  |

        git clone -b ci-gh https://github.com/mattd3v/Open-Source-Ventilator.git
        cd Open-Source-Ventilator/OpenSourceVentilator/
        arduino-cli compile --warnings all --fqbn arduino:avr:uno -o osv-controller-uno.bin OpenSourceVentilator.ino
        find .
  artifacts:
    paths:
    - ./osv-controller-uno.bin.hex
    - ./osv-controller-uno.bin.elf

```

Pipeline output:

```
.
./test
./test/RMVS_TestCaseData.xlsx
./OpenSourceVentilator.ino
./osv-controller-uno.bin.hex
./osv-controller-uno.bin.elf
./README.md

section_end:1586713988:build_script
[0Ksection_start:1586713988:after_script
[0;msection_end:1586713990:after_script
[0Ksection_start:1586713990:archive_cache
[0K[0K[36;1m Saving cache[0;m
[0;msection_end:1586713991:archive_cache
[0K section_start:1586713991:upload_artifacts_on_success
[0K [0K [36;1m

Uploading artifacts for successful job[0;m
[0;m[32;1m
Uploading artifacts...[0;m

[0;33m WARNING: ./osv-controller-uno.bin.hex: no matching files[0;m
[0;33m WARNING: ./osv-controller-uno.bin.elf: no matching files[0;m

[31;1mERROR: No files to upload                         [0;m
section_end:1586713993:upload_artifacts_on_success
[0K[32;1mJob succeeded
[0;m

```

# Answer
As Casey Vega commented: provide the complete path.
> 1 votes

---
Tags: continuous-integration, gitlab, linux
---


# Question
Title: How to restrict access on changing task status in Azure Devops
My manager would like to use the Azure DevOps board feature to keep track of her employee's tasks but asked if there is a way so that only she can move or closeout task items. It's a process control issue. Can changing the status (TODO, DOING, DONE) of a task item in Azure DevOps be locked down to a certain role or user account?

# Answer
From your own comment below your question, it seems that Set permissions and access for work tracking is a possible answer. Here is a partial quote of it:

> You grant or restrict access to various work tracking features by granting users or groups specific permissions for an object, project, or collection. Or, when you assign a user as a team administrator, they have permissions to manage all assets for the specific team. Add users to the Contributors group to provide access to most features as listed in Permissions and access for work tracking.
> 0 votes

---
Tags: azure-devops
---


# Question
Title: Trying to migrate CI/CD process from Jenkins to Gitlab Runner + Docker on Windows
I need to improve the CI process of my projects, which is basically composed of the following things:

* a Linux server, that contains a Jenkins master
* a VM with **Windows 10**, with a Jenkins slave, responsible to build one of my projects (that uses .NET core, .NET framework, Node.JS and nmake)
* a Jenkins pipeline job that compiles the project (**assuming the needed tools are already installed**) -\> *this is used to generate final released versions to the customer*
* a Gitlab Runner on some Windows machines (configured as 'shell' executors) -\> *this is seamlessly used with our gitlab, for continuous integration and pipelines, to be visible on Merge Requests, for instance*

**Problems:** we manually entered the VM above and installed all the tools needed to build the applications. If the projects require new tools, we need to manually enter the machines and install them prior to running the build jobs.

**What I want:** I plan to improve this CI environment with Docker (however I'm pretty new to it), to be able to **easily scale** the job runners. I'm thinking about using less Jenkins and more Gitlab Runner instances (configured as 'docker' executor), to be able to **delegate** the CI/CD processes to each '.yml' file versioned on each project.

To accomplish the above, I thought about some approaches:

## Put a Gitlab Runner configured as 'docker+machine'

This spawns as many 'docker' runners as needed --\> this is easily scalable

**Problem:** "Docker Machine" only creates Linux VMs, and I need specifically for this project a Windows environment for the build

## Use a Gitlab Runner configured as 'docker'

This should be scalable, if it spawns containers for building on demand.

Based on this scenario, I have a couple of questions:

1. do you have any suggestion about how can I create a docker image that is able to build my project? I need to use Windows OS, .NET core, .NET fw, nmake, Node.Js. Do you have some specific images recommended for this task?
2. should I create a 'sdk' docker image (an image with all tools needed for building and testing) separate from my project source-code, and publish this image to Docker Hub, and 'consume' it on my gitlab runner? I mean, what's the best practice for this case, supposing my customer does not have a private Docker Registry?
3. have anyone tried this scenario (gitlab runner + docker on Windows) before, and have some feedback if it works or not?
4. Is my plan of decreasing Jenkins usage and using more Gitlab runner (for this project at least) feasible? I thought about this because we currently have to manage a "Jenkins Master" and all "Jenkins Slaves" machines. With this new approach, the 'master' would be actually the entire Gitlab instance, and the 'slaves' would be several GL runners deployed as I need, on which I would delegate the job to each project's ".yml" file;
5. Do you have a better approach on how can I improve to a scalable Windows project CI/CD process, other than using gitlab runner + docker?

# Answer
> 1 votes
> have anyone tried this scenario (gitlab runner + docker on Windows) before, and have some feedback if it works or not?

I installed and registered a GitLab Runner on my Windows 10 laptop following the instructions from GitLab Install GitLab Runner on Windows

At first, I had trouble pulling the Windows container image:

```
PS C:\GitLab-Runner> docker pull mcr.microsoft.com/windows/servercore
Using default tag: latest
Error response from daemon: manifest for mcr.microsoft.com/windows/servercore:latest not found: manifest unknown: manifest unknown
PS C:\GitLab-Runner> docker pull mcr.microsoft.com/windows/servercore:1809
1809: Pulling from windows/servercore
no matching manifest for linux/amd64 in the manifest list entries
PS C:\GitLab-Runner>

```

After selecting the "Switch to Windows containers" option in my Windows Docker (in the top-level menu that opens from the Docker icon in the toolbar), I was able to `docker pull` the Windows servercore image.

However, I was unable to run GitLab Runner on my fully patched and updated Windows laptop:

```
 ERROR: Preparation failed: unsupported Windows version: Windows 10 Pro Version 1909 ...

```

It's too new! As I read GitLab's Windows version support policy, GitLab should support 1909 for 18 months; but obviously that is not the case yet. 1903 is the most recent supported version.

However, as of January 2020, GitLab has Windows Shared Runners (beta)

I tried that and it works. Example `.gitlab-ci.yml`:

```
my_job:
  script: systeminfo
  tags:
    - windows

```

> Is my plan of decreasing Jenkins usage and using more Gitlab runner (for this project at least) feasible?

Sounds good to me.

> Do you have a better approach on how can I improve to a scalable Windows project CI/CD process, other than using gitlab runner + docker?

No. I think you're on the right path.

---
Tags: docker, gitlab, windows, cicd, gitlab-ci-runner
---


# Question
Title: Gather resource usage by process in a kubernetes cluster
I am searching for a tool similar to Prometheus + Grafana that gather and record resource usage especially memory usage by process-ID or process-name.

We have two components that are running different processes and they have memory leak and I want to find which process is leaking.

This is from Weave Scope and it shows all the processes of each pod and their resource usage but it is just live, I want something similar but storing it over time like a Prometheus graph.

# Answer
> 0 votes
There are several alternatives to Prometheus for monitoring your cluster.

While some like Heapster have been superseded by Prometheus, other solutions such as cAdvisor may have the functionality you are looking for.

# Answer
> 0 votes
Prometheus can surface any metrics you like, you just need a proper exporter for the apps. E.g. there will be JVM exporters to export JVM heap metrics. Many apps support JMX (also in Java), or other similar mechanisms in other languages for reporting metrics and counters as well (e.g. we use these to get detailed presto memory use metrics).

You may want process exporter or something similar -\> https://github.com/ncabatoff/process-exporter.

If you really had to, you could even write something as simplistic as a kubectl exec command to grab stats from the container and save them in prometheus exporter file format and scrape it off apache/nginx.

Other than that, go for a good APM solution that holds the metrics for you and fork out some cash =).

---
Tags: kubernetes, monitoring, prometheus
---


title: Gitlab doesn't open Word files

text:
# Question
Title: Gitlab doesn't open Word files
I'm uploading docx file in Gitlab, however it doesn't preview it.

It only downloads it.

Is it fixable?

# Answer
You can only view text/source code files, Markdown files and images. Gitlab doesn't have a preview option for other files such as proprietary word processors.
> 13 votes

# Answer
A word document is not a source document that is fit for version control, it's a proprietary binary file.

For version control, try to learn a real source document like e.g. Markdown or AsciiDoc. In this way you'll be able to preview in Gitlab or Github, even with Windows.

While still being able to publish it after rendering it with e.g. Pandoc to a .docx or .pdf, .html, RTF, ODT, EPUB or all of them with an optional version tag.
> 4 votes

# Answer
DOCX actually is zip-archive which contains xml. Xml is text format which should be fine viewed and tracked by Gitlab and other version control systems. Unfortunately, now this feature is unavailable. But exists alternative path - use third-side utility Pandoc.

I found information about Pandoc at this link: https://github.com/vigente/gerardus/wiki/Integrate-git-diffs-with-word-docx-files
> 0 votes

---
Tags: gitlab
---


title: Angular config maps in kubernetes

text:
# Question
Title: Angular config maps in kubernetes
How can I integrate a config map into my angular application in kubernetes?

Any useful blogs or videos implementing this would be helpful. I found a few, but they didn't work for me.

# Answer
This one from medium should be fine for your purposes: https://medium.com/@ychetankumarsarma/how-to-manage-angular-application-configurations-for-different-environments-with-docker-and-8ff8c55a1c7d.

It is good because:

* It shows a test / development scenario.
* It notes that it is a good / accepted technique to use environment variables to drive config.
* It shows you how to create a config map with a literal value (as an example).
* It shows you how to read that environment variable into your app environment properly.

There is also a working sample app noted here -\> https://github.com/chetanku/frontend-env which you should be able to "just start up" and work backwards from.
> 3 votes

---
Tags: kubernetes, configuration-management, kubernetes-volume
---


# Question
Title: I was trying ti set up presto with azure gen2 , but facing the below issue when I am querying
I am using `prestodb:0.234`

Dependency jars:

```
   azure-storage-2.0.0.jar
   hadoop-azure-3.2.1.jar
   hadoop-azure-datalake-3.2.1.jar
   azure-data-lake-store-sdk-2.3.8.jar

```

I am getting below error while doing the querying.

```
com.facebook.presto.spi.PrestoException: cannot create caching file system
    at com.facebook.presto.hive.HiveCachingHdfsConfiguration.lambda$getConfiguration$0(HiveCachingHdfsConfiguration.java:70)
    at com.facebook.presto.hive.HiveCachingHdfsConfiguration$CachingJobConf.createFileSystem(HiveCachingHdfsConfiguration.java:94)
    at org.apache.hadoop.fs.PrestoFileSystemCache.get(PrestoFileSystemCache.java:59)
    at org.apache.hadoop.fs.FileSystem.get(FileSystem.java:373)
    at org.apache.hadoop.fs.Path.getFileSystem(Path.java:295)
    at com.facebook.presto.hive.HdfsEnvironment.lambda$getFileSystem$0(HdfsEnvironment.java:73)
    at com.facebook.presto.hive.authentication.NoHdfsAuthentication.doAs(NoHdfsAuthentication.java:23)
    at com.facebook.presto.hive.HdfsEnvironment.getFileSystem(HdfsEnvironment.java:72)
    at com.facebook.presto.hive.HdfsEnvironment.getFileSystem(HdfsEnvironment.java:66)
    at com.facebook.presto.hive.BackgroundHiveSplitLoader.loadPartition(BackgroundHiveSplitLoader.java:298)
    at com.facebook.presto.hive.BackgroundHiveSplitLoader.loadSplits(BackgroundHiveSplitLoader.java:270)
    at com.facebook.presto.hive.BackgroundHiveSplitLoader.access$300(BackgroundHiveSplitLoader.java:100)
    at com.facebook.presto.hive.BackgroundHiveSplitLoader$HiveSplitLoaderTask.process(BackgroundHiveSplitLoader.java:199)
    at com.facebook.presto.hive.util.ResumableTasks.safeProcessTask(ResumableTasks.java:47)
    at com.facebook.presto.hive.util.ResumableTasks.access$000(ResumableTasks.java:20)
    at com.facebook.presto.hive.util.ResumableTasks$1.run(ResumableTasks.java:35)
    at com.facebook.airlift.concurrent.BoundedExecutor.drainQueue(BoundedExecutor.java:78)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
Caused by: java.io.IOException: No FileSystem for scheme: abfs
    at org.apache.hadoop.fs.FileSystem.getFileSystemClass(FileSystem.java:2660)
    at org.apache.hadoop.fs.PrestoFileSystemCache.createFileSystem(PrestoFileSystemCache.java:114)
    at org.apache.hadoop.fs.PrestoFileSystemCache.getInternal(PrestoFileSystemCache.java:89)
    at org.apache.hadoop.fs.PrestoFileSystemCache.get(PrestoFileSystemCache.java:62)
    at org.apache.hadoop.fs.FileSystem.get(FileSystem.java:373)
    at org.apache.hadoop.fs.Path.getFileSystem(Path.java:295)
    at com.facebook.presto.hive.HiveCachingHdfsConfiguration.lambda$getConfiguration$0(HiveCachingHdfsConfiguration.java:66)

```

Any suggestions?

# Answer
Since `ABFS` mentioned in the stacktrace as a caching filesystem, then I suppose two possible reasons and suggest solutions for them

## Dependency mesh in `maven`

As noted in two answers (one, two) to a similar question

> When we use maven-assembly-plugin, it merges all our JARs into one, and all META-INFO/services/org.apache.hadoop.fs.FileSystem overwrite each-other. Only one of these files remains (the last one that was added). In this case, the FileSystem list from hadoop-commons overwrites the list from hadoop-hdfs, so DistributedFileSystem was no longer declared.

So, check your dependencies and if there are `JAR` with correct `org.apache.hadoop.fs.FileSystem` in your distibution.

## `PrestoDB` uses outdated `azure-site.xml`

There is known issue #11648. And as said, `ABFS`, `ADLS` and `ALDS gen2` was only introduced to https://github.com/prestosql/presto, not to `prestodb`

So, suggestion is to ask your question on Presto Community Slack

# P.S. try `storediag`

There is a `hadoop` manual on `Azure` ABFS

And among other tips they recommend:

> One useful tool for debugging connectivity is the cloudstore storediag utility.
>
> This validates the classpath, the settings, then tries to work with the filesystem.
> 2 votes

---
Tags: azure, java, hive
---


# Question
Title: How to prohibit access to internals of Docker container?
I want to deliver my app to customers in form of docker image. But it is crucial to ensure that end-user do not alter anything inside the container. User should only be able to run/stop the container and interact with the container via network.

Is it possible to prohibit access to internals of container? Is it possible to verify integrity of image that container made from?

# Answer
> 18 votes
In short, you cannot prevent your customers from modifying containers they run in their own infrastructure. Containers are not like binaries that can be obfuscated; they are runtime environments. The code you distribute inside the container, however, can be obfuscated.

Your question alludes to a third-party support issue: clients modifying software they run in their own environments. If you provide tools to *operate* the containers you supply (e.g. monitoring and logging) then the clients should agree (as part of a software license) not to make unauthorized modifications to them. This applies to all types of third-party software, not just containers.

Depending on your situation, you may also have the option to provide your app as Software As A Service (SaaS) running in a cloud infrastructure.

If your client requires your containers be run on their infrastructure, and refuses to abide by modification restrictions, then you probably don't want to try to support their use of your software.

# Answer
> 9 votes
Docker doesn't provide any means to preclude user access to the container, however as the image developer you could follow a few strategy

* Obfuscate your software (ruby, python and etc)
* Build your image from a base image that doesn't have shell, and other binaries that the user can use to tramper the image.

Of course they can always export the container and repackage it but those are extreme measures...

# Answer
> 6 votes
If your client is ready to invest money then you should go with Docker enterprise edition. In Docker EE you have one tool that is `UCP(Universal Control Plane)` UCP. By UCP you can create roles and access rights and restrict the user to change/modify containers.

If you want to test UCP than DDC(Docker Data Center) having one month trial license which will help you to elaborate the things as per your requirements.

# Answer
> 5 votes
You can remove the users from the docker group and create sudos for the `docker start` and `docker stop`.

# Answer
> 2 votes
Give your delivery via ansible scripts. Keep all sort of restrictions and checks in the ansible script.

# Answer
> 0 votes
You have no problem at the first place. An image in Docker is not like a monolithic ISO. It has layers. And layers in Docker, when you run them, are immutable.

For example:

* Somebody built Alpine image with hash abc123
* Then somebody build a Python image based on Alpine (FROM alpine:abc123) with hash def456.
* Now you've build your image atop of Python (FROM python:def456) and result in hash ghi789.

Now your customer is pulling the image:

```
docker pull flask:ghi789

```

When he runs his container he gets three read-only layers in memory (abc123, def456 and ghi789) and one new read-write layer jkl357 that is initially empty. It will be filled later with some data during app activity, for example - logs, or external connections like "docker exec ...". Thus, no matter what customer does in his new layers, all precommitted layers are safe.

The layer jkl357 become immutable (readonly) only upon commit. But this is already not your image SHA and not related to you app:

```
docker commit -t my-altered-flask:tag

```

---

All said is relevant unless your goal is to protect from modifying, not from read at all.

---
Tags: docker, security
---


# Question
Title: GitLab CI/CD page listing many gitlab runners that no longer exist
I am running `GitLab Runner` using a `Helm` chart as described on the GitLab Runner Helm Chart page.

Everything seems to be working, but after about two months of running I see on my `GitLab` group that controls the `GitLab runner` on the "CI / CD Settings|Runners" page the message

> "Available group Runners: 54".

Here is the first couple on that page:

Rather than listing all 54 here is the list run through `uniq -c`:

```
      3 gitlab-runner-gitlab-runner-9fcb644b9-4f5ss
      2 gitlab-runner-gitlab-runner-9fcb644b9-4gqqq
      1 gitlab-runner-gitlab-runner-9fcb644b9-889rc
      2 gitlab-runner-gitlab-runner-9fcb644b9-grb5j
      1 gitlab-runner-gitlab-runner-9fcb644b9-hhv8f
      1 gitlab-runner-gitlab-runner-9fcb644b9-kzcdv
     13 gitlab-runner-gitlab-runner-9fcb644b9-nvrms
      7 gitlab-runner-gitlab-runner-9fcb644b9-pl2k4
      2 gitlab-runner-gitlab-runner-9fcb644b9-sxlmp
      9 gitlab-runner-gitlab-runner-9fcb644b9-vdmsj
      3 gitlab-runner-gitlab-runner-9fcb644b9-vgdnv
      8 gitlab-runner-gitlab-runner-9fcb644b9-wst8q
      2 gitlab-runner-gitlab-runner-9fcb644b9-xnzhx

```

Looking at my `GitLab Runner` `Kubernetes` container there seems to be only *one* runner:

```
$ /usr/bin/gitlab-runner list
Runtime platform                                    arch=amd64 os=linux pid=4953 revision=1b659122 version=12.8.0
Listing configured runners                          ConfigFile=/home/gitlab-runner/.gitlab-runner/config.toml
gitlab-runner-gitlab-runner-9fcb644b9-grb5j         Executor=kubernetes Token=XXXXXXXXXXXX-XXXXX URL=https://myserver.example.com/

```

Another potentially important piece of information: the `Kubernetes` node that hosts the `GitLab Runner` container is preemptible meaning it gets killed and restarted about every 24 hours.

How do I convince `GitLab` that these old runners are not still around? And how do I avoid this problem in the future?

# Answer
## Just unregister offline runners:

As per GitLab Runner commands manual:

> To delete the old and removed from GitLab runners, execute the following command.

```
    gitlab-runner verify --delete

```

## You are not alone

P.S. The problem is common: there are many issues with questions like yours.

Moreover, there are several custom recipes to unregister "offline" runners:

## API for "zombie" runners

As rlandster noted, sometimes you'll need an API to unregister "zombie" runners.

```
curl -S --header "PRIVATE-TOKEN:<token>" "https://gitlab.example.com/api/v4/runners/all" | jq '.[] | select(.status == "offline") | .id' | xargs -I runner_id curl -S --request DELETE --header "PRIVATE-TOKEN:<token>" "https://gitlab.example.com/api/v4/runners/runner_id"`

```

This will list all runners, instead of the personal ones: https://docs.gitlab.com/ee/api/runners.html#list-all-runners

## P.S. note about runners

Pls note that `Gitlab` itself doesn't manage runners. So, e.g. to restart or shutdown the runner, use appropriate commands on the runner's hosts.
> 3 votes

---
Tags: kubernetes, gitlab, gitlab-ci-runner, helm
---


title: Infrastructure Automation with GitLab

text:
# Question
Title: Infrastructure Automation with GitLab
I am looking to validate the use of devops for a team of seven people, each having a specific function.

1 Java Developer
1 System Administrator
1 Team Lead/Project Manager
1 Identity Management Admin
2 Access Management Admin
1 PKI Registration Agent

We have different workflows for each function. However, from my perspective, it's all the same. New ideas or requirements bring about new or changes to code, which initiates the workflow. To me, application updates, OS patching, and innovation are all the same. Could CI/CD pipelines be created to standardize infrastructure security and configuration as well as enable a faster and more feature tuned application release cycle? Any input would be most appreciated.

-Darryl

# Answer
here are my 2 cents,

1. You can use GITLAB to have merge requests for all your security requests like adding users to the groups for every new user or existing users. the Mr can be approved by only your IAM admin. You can use GITLAB CI pipelines to go and perform the operation once the MR is approved. From the users side, the user has to provide their keys and submit as an MR so that the IAM team can validate and approve it.
2. You can deploy your applications easily using Ansible and Gitlab CI. All you need is just source code of your application and some knowledge of YAML. I am sure, your folks already are equipped with that. Ansible can be used for infra provisioning as well so you can just run the show with them. With regards to os updates, I would say ansible can easily do it. Have the SDLC workflow in place for developing playbooks and once the playbook is modularized, it can used in production.

Let me know if I answered your query and if you have any other questions.
> 2 votes

# Answer
You have a lot of ways to automatize you infrastructure. For your pipelines you can use a tool for this like Jenkins, Travis CI, GitLab, Concourse CI, Drone IO and through turn better CI/CD for your developer.

From the perspective of automating the infra, you can use Terraform to raise it, manage to maintain the default using Ansible and to handle jobs you can use Rundeck.

But the more important it's you plan how to you link these tools.
> 1 votes

---
Tags: automation, infrastructure-as-code, workflow
---


# Question
Title: Build Docker images with DinD and BuildKit
I use GitLab's pipelines to describe the deployment process. And, as part of it, I build Docker images. For that purpose, I use Docker-in-Docker to build those images (i.e. download the `Docker-in-Docker` image and do all the Docker-stuff, inside of it).

I also set to use Docker Buildkit features. And one of them is `--cache-from` option (which decreases build time). Which seems doesn't work with `Docker-in-Docker` (at least, for me).

Here's the pipeline's config:

```
stages:
  - build
  - purge
  - deploy

variables:
  DOCKER_HOST: tcp://localhost:2375
  DOCKER_TLS_CERTDIR: ""
  DOCKER_BUILDKIT: 1
  LATEST: ${CI_REGISTRY_IMAGE}/${CI_PROJECT_NAME}:${CI_COMMIT_REF_SLUG}
  IMAGE_COMMIT_TAG: ${CI_REGISTRY_IMAGE}/${CI_PROJECT_NAME}:${CI_COMMIT_SHORT_SHA}

services:
  - docker:dind

build:
    stage: build
    image: docker:stable
    script:
        - docker login -u gitlab-ci-token -p ${CI_BUILD_TOKEN} ${CI_REGISTRY}
        - docker build --cache-from ${LATEST} -t ${LATEST} -t ${IMAGE_COMMIT_TAG} .
        - docker push ${IMAGE_COMMIT_TAG}
        - docker push ${LATEST}

```

The log output shows the `BuildKit` is engaged, but there's nothing about using of 'CACHE'. And, the result of it -- 'build' stage takes much more time.

Please, your suggestions, ideas?

# Answer
Caching of layers with buildkit in an external registry requires an extra step or two depending on how you want to cache your layers. The easy option is to include a build arg that enables the inline cache:

```
docker build --build-arg BUILDKIT_INLINE_CACHE=1 --cache-from ${LATEST} -t ${LATEST} -t ${IMAGE_COMMIT_TAG} .

```

Note that the inline cache only caches layers for the target stage that was pushed in the image, so other states in a multi-stage build would need to be built and cached separately, or rebuilt without caching, neither of which is ideal.

You can also cache to a local file, or push the cache to a different registry image rather than inline with the image you pushed. Unfortunately the standard `docker build` CLI doesn't have access to all the buildkit flags to enable this. Instead, you can install buildkit directly or use buildx which is a CLI plugin for managing buildkit. You can install buildx separately but in current releases it's available with experimental CLI options that can be enabled with `export DOCKER_CLI_EXPERIMENTAL=enabled`. I believe you'd need to create a container based builder for all of the buildkit options, which can be done with:

```
docker buildx create --use --driver docker-container --name local ${DOCKER_HOST:-unix:///var/run/docker.sock}

```

Then you should be able to run something like:

```
docker buildx build --cache-from ${IMG_CACHE} --cache-to ${IMG_CACHE} -t ${LATEST} -t ${IMAGE_COMMIT_TAG} .

```

More documentation on the buildkit caching is available at: https://github.com/moby/buildkit#export-cache

More details on buildx is available at: https://github.com/docker/buildx
> 4 votes

# Answer
Though it's not the direct answer to my question, but it's a goal, I was aimed at.

I tested several image build tools and stopped on 'Makisu', for building Docker images. It really works fine for me.

The details are here: https://github.com/uber/makisu

and here (starting from 'Using Makisu'): https://findwork.dev/blog/6-ways-speed-your-ci/
> 0 votes

---
Tags: docker, gitlab, gitlab-ci-runner, docker-in-docker
---


# Question
Title: Why are unnamed volumes created when `docker-compose up` is run and do these double after issuing `docker-compose down && docker-compose up`?
When starting a docker compose application, it creates named volume the first time around and then additional volumes each time it is started. Is this the normal behavior in that it creates incremental volumes or is my docker-compose file broken? In addition, after running `docker volume prune`, it removed two of the unnamed volumes

This is the output after starting it twice:

```
DRIVER              VOLUME NAME
local               2b33c81e6e955ff36061f4120b7181c7efc7aebded2f87eaa7290027f1e7a725
local               74301eadc75018d6f7da76aec44bcf743e03261492cfcc33211941684a570030
local               c42b1e2c17342c52b4b9e90f4d4b7fa24ccb30de5479e65cf4366e2373dfb0bf
local               dcfa63dbf99362fc92fe3b981f50abebfe1bba03063d4dd9dd790f4c058817cf
local               dockerinfluxdbgrafana_grafana-data
local               dockerinfluxdbgrafana_influxdb-data

```

And for reference my docker-compose file

```
version: "3"
services:
  influxdb:
    image: influxdb:latest
    container_name: influxdb
    ports:
      - "8086:8086"
    env_file:
      - 'env.influxdb'
    networks:
      - backend
    volumes:
      - influxdb-data:/var/lib/influxdb

  grafana:
    image: grafana/grafana:latest
    container_name: grafana
    ports:
      - "3000:3000"
    env_file:
      - 'env.grafana'
      - 'secrets.grafana'
    networks:
      - backend
    volumes:
      - grafana-data:/var/lib/grafana

networks:
  backend:

volumes:
  influxdb-data:
  grafana-data:

```

**Steps to reproduce**

```
docker-compose up -d && docker-compose down && docker-compose up -d && docker-compose down && docker-compose up -d && docker-compose down

```

# Answer
> 11 votes
Research indicated that the anonymous volumes were created by `influxdb` and `grafana/grafana`.

> Anonymous volumes are not given an explicit name when they are first mounted into a container, so Docker gives them a random name that is guaranteed to be unique within a given Docker host. Besides the name, named and anonymous volumes behave in the same ways.

**Results**

```
version: "3"
services:
  influxdb:
    image: influxdb:latest
    container_name: influxdb
    ports:
      - "8086:8086"
    #env_file:
    #  - 'env.influxdb'
    networks:
      - backend
    volumes:
      - influxdb-data:/var/lib/influxdb

  grafana:
    image: grafana/grafana:latest
    container_name: grafana
    ports:
      - "3000:3000"
    #env_file:
    #  - 'env.grafana'
    #  - 'secrets.grafana'
    networks:
      - backend
    volumes:
      - grafana-data:/var/lib/grafana

networks:
  backend:

volumes:
  influxdb-data:
  grafana-data:

```

results in:

```
DRIVER              VOLUME NAME
local               604a07040367512b09c618c6dcc71a7f55390c9c23de6ab08be7466414ed62da
local               7f4b630073b31b6e772d3edef6da81b48643525edfc34281ea13fbd6b86ec270
local               devopsstackexchange_grafana-data
local               devopsstackexchange_influxdb-data

```

and everytime when `docker-compose down` and subsequenlty `up` is run the number of anonymous volumes doubles.

*What will happen if nginx will be pulled instead of influxdb and grafana?*

```
DRIVER              VOLUME NAME
local               devopsstackexchange_grafana-data
local               devopsstackexchange_influxdb-data

```

and after `docker-compose down && docker-compose up -d`?

```
DRIVER              VOLUME NAME
local               devopsstackexchange_grafana-data
local               devopsstackexchange_influxdb-data

```

It looks like that certain images created the additional anonymous volumes. Let's replace influxdb with nginx and use grafana.

```
DRIVER              VOLUME NAME
local               15b80416ab06abb629d9f634a0feff08f7c560f31d614b9b430855c16cdb75c7
local               205a6f19cbf992c95b2e3be9f2fb1ca9ecec35fce550d0b7a4b9f32b0ef163b1
local               474108f5b7b14fba92a3e5a980f3bf851388b2ee25d7417df5c42d9f176e084b
local               5830a31a470ec8a42ddae7a37bb50487f3f36360318b2f9f5301b338507782b4
local               9f00868a2fec0cfc0d34dc12d0879d39487a13128863722f400ad4c47df2d340
local               devopsstackexchange_grafana-data
local               devopsstackexchange_influxdb-data
local               f47b1b7bbec8e50b32a7c39704c7c218165b284298d852313fa24bc7cbe6acc5

```

Everytime docker compose was run again, three anonymous volumes were created by the `grafana/grafana` docker image. Let's replace influxdb with nginx and revert the grafana to nginx:

```
DRIVER              VOLUME NAME
local               devopsstackexchange_grafana-data
local               devopsstackexchange_influxdb-data

```

and it remains two if restarted.

It looks like that grafana is causing the issue.

**Why are three new anonymous volumes created everytime grafana/grafana is restarted?**

The grafana/grafana dockerfile indicates that three anonymous volumes will be created:

> ```
> VOLUME ["/var/lib/grafana", "/var/log/grafana", "/etc/grafana"]
>
> ```

https://docs.docker.com/engine/reference/builder/#volume

> ```
> FROM ubuntu
> RUN mkdir /myvol
> RUN echo "hello world" > /myvol/greeting
> VOLUME /myvol
>
> ```
>
> This Dockerfile results in an image that causes docker run, to create a new mount point at /myvol and copy the greeting file into the newly created volume.

`docker volume inspect <volume name, e.g. 34cfafd4603dbc7e71a83e2520f978c8307b084143b3192de65a1995dc1d2f86>` returned grafana data when the path that was returned was checked of two out of three anonymous volumes:

```
sudo ls /var/lib/docker/volumes/a0ecd00df8fc68ef36e777c7bf9ec5a496ee30e313b86889487501a53fa2e28e/_data
grafana.ini  ldap.toml

```

and

```
sudo ls /var/lib/docker/volumes/34cfafd4603dbc7e71a83e2520f978c8307b084143b3192de65a1995dc1d2f86/_data
grafana.db  plugins

```

# Answer
> 3 votes
Check the volumes defined in the `Dockerfile` with the `VOLUME` instruction.

If you don't want volume with random names to be automatically created, you can provide a host path to be bind-mounted to the volume, check the `-v` or `--mount` options, https://docs.docker.com/engine/admin/volumes/volumes/#choose-the--v-or-mount-flag

For example:

```
-v /srv/lib/grafana:/var/lib/grafana

```

# Answer
> 1 votes
If anyone else is going down this rabbit hole. Make sure you didn't accidentally define your volume with an `=` in your `Dockerfile`

**Wrong:**

```
VOLUME = ["/logs", "/data"]

```

**Correct:**

```
VOLUME ["/logs", "/data"]

```

It took me a long time to dig into why the anonymous volumes were being added by `docker-compose`

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


# Question
Title: How to locally resolve host name starting with variable slug?
An app, running on my laptop in development mode, comprises several Docker containers, one of which runs a Django web app.

This web app expects to receive HTTP requests using a hostname with a variable leading part, e.g. "test-account.survey.com", in which 'test-account' is a slug representing a particular account, and the remaining string 'survey.com' is fixed.

Now I know this can be resolved in a Live environment, involving external HTTP requests, by using wildcard DNS servers \[ https://en.wikipedia.org/wiki/Wildcard\_DNS\_record \].

But I'd like to set up and configure on my laptop a local DNS server for the sole purpose of forwarding hostnames as above to a fixed IP address, e.g. 127.0.0.1 and "passing through" any other hostnames.

Any recommendations? Thanks in anticipation.

P.S. The DNS server must support Windows 10 and Mac OS.

# Answer
People often use dnsmasq for this. You can wildcard sub-domains like this fairly easily for local testing using it.

Here's an example - https://qiita.com/bmj0114/items/9c24d863bcab1a634503 but there are plenty online.
> 1 votes

---
Tags: docker, dns
---


title: Terraform conditionally create VPC

text:
# Question
Title: Terraform conditionally create VPC
I am in the process of creating a terraform template, part of which can create a VPC.

The user has the option to specify the parameter `create-vpc`. This will be passed to the module https://github.com/terraform-aws-modules/terraform-aws-vpc which will create the VPC based on this parameter i.e.

```
module "vpc" {
  source = "terraform-aws-modules/vpc/aws"

  create_vpc = var.create-vpc
  # ... omitted
}

```

I am now trying to use a `data` source to share the VPC with the rest of my template i.e.

```
data "aws_vpc" "myvpc" {
  id = "${module.vpc.vpc_id}"
}

```

How can I update this to use the variable `vpc-id` instead of the module output if the VPC hasn't been created?

Ideally I'd do something like:

```
data "aws_vpc" "myvpc" {
  count = "${var.vpc-id != "" ? 1 : 0}"
  id = "${module.vpc.vpc_id}"
}

data "aws_vpc" "myvpc" {
  count = "${var.vpc-id != "" ? 0 : 1}"
  id = var.vpc-id
}

```

This won't work as resource names need to be unique.

Other resources in the template reference this VPC.

# Answer
The way I'm understanding your question is that you're writing a module that takes an optional `vpc_id` as an argument, and either uses it if specified or creates a new VPC itself if not specified. You then need to use the VPC id elsewhere in your configuration, regardless of whether it was provided by the caller directly or if it was created by the VPC module.

If I understood that correctly, here's one way to get that done.

First, we'll declare the `vpc_id` variable for your own module that the rest of this will use to make its decisions.

```
variable "vpc_id" {
  type    = string
  default = null # optional with no default value
}

```

From this we will derive our decision about whether to create the VPC, which I'll write as a local value here mainly for exposition purposes but you might choose to inline it at the point of use in practice depending on what feels most readable for you:

```
locals {
  create_vpc = var.vpc_id != null ? true : false
}

```

We can now use that value both with the module and with a `data` resource so that we'll either create a new VPC or retrieve data about the existing one:

```
module "vpc" {
  source = "terraform-aws-modules/vpc/aws"

  create_vpc = local.create_vpc
  # ...
}

data "aws_vpc" "selected" {
  count = local.create_vpc ? 0 : 1

  id = var.vpc_id
}

```

We can then write another local value that chooses which of those two locations to derive other VPC-related values, such as the `id` and `cidr_block` from:

```
locals {
  vpc = (
    local.create_vpc ?
    {
      id         = module.vpc.vpc_id
      cidr_block = module.vpc.vpc_cidr_block
    } :
    {
      id         = data.aws_vpc.selected.id
      cidr_block = data.aws_vpc.selected.cidr_block
    }
  )
}

```

You can then use `local.vpc.id` and `local.vpc.cidr_block` elsewhere in the configuration to get the appropriate values to use regardless of whether this module created its own VPC or not.

---

The above is the most direct answer to your question. I also wanted to share a different approach that is based on the patterns described in the Module Composition section of Terraform's docs, which might be appropriate for you if you're building a shared module intended to be called by another Terraform module.

A different way to approach this problem using composition is to say that your module *never* creates its own VPC, and always expects one to be provided to it. This is an example of the *dependency inversion* principle. Here's how that might look for your particular use-case...

In your module, you can declare an input variable called `vpc` that has the same structure as the final `local.vpc` that we created in the previous approach:

```
variable "vpc" {
  type = object({
    id         = string
    cidr_block = string
  })
  # This time the VPC is required. The caller decides how to obtain it.
}

```

Your own module's expressions would then get the VPC id as `var.vpc.id` instead of `local.vpc.id` as in the previous approach.

The calling module can then decide between several different ways of providing the value for that variable:

```
# Using the terraform-aws-modules/vpc/aws module
module "vpc" {
  source = "terraform-aws-modules/vpc/aws"

  # ...
}

module "your_module" {
  source = "./modules/your-module"

  vpc = {
    id         = module.vpc.vpc_id
    cidr_block = module.vpc.vpc_cidr_block
  }
}

```

```
# Directly using the aws_vpc resource type

resource "aws_vpc" "example" {
  # ...
}

module "your_module" {
  source = "./modules/your-module"

  vpc = aws_vpc.example
}

```

```
# Using the aws_vpc data source to find an existing VPC

data "aws_vpc" "example" {
  tags = {
    Environment = "STAGE"
  }
}

module "your_module" {
  source = "./modules/your-module"

  vpc = data.aws_vpc.example
}

```

In other words, this lets your new module focus on whatever new problem it is trying to solve while being decoupled from the problem of creating a VPC, allowing the calling module to obtain that VPC information in whatever way is appropriate. The appropriate way to obtain the VPC might change over time, and this composition approach means that callers can have more control over how they manage the transition between different approaches, independent of the implementation of your new module.

Module composition isn't always the best option, but I wanted to point it out because the Terraform documentation specifically recommends considering this approach and recommends against having many levels of nested module calls.
> 2 votes

---
Tags: terraform
---


# Question
Title: Are there cheaper alternatives to cloud watch logs for creating dash boards?
Iv set up a grafana instance.

I want to create dashboards to get metrics on lambda functions but useing cloud watch logs would be expencive.

Are there any cheaper alternatives to achive this that might be worth looking at?

# Answer
Grafana was not really built to view logs from the get go.

They however introduced this feature in v6.0 via the Explore tab

This can be leveraged in 2 ways.

## Via Elasticsearch data source (in v6.3+)

Check the Elasticsearch docs for more.

If you want, you can still integrate this with Cloudwatch. Check out the log subscirber-consumer solution & this

## Via Loki & AWS Lambda

If you want to stick to Cloudwatch as your primary source of logs, you can create a Lambda function that ships them to Loki which in tern can be used in Grafana as a data source. See ,  &
> 1 votes

---
Tags: metrics, grafana
---


# Question
Title: unable to login using docker registry on jenkins
I have a Jenkinsfile that I need to login to ECR. this is the relevant section

```
        script {
          docker.withRegistry('https://01234.dkr.ecr.ap-southeast-1.amazonaws.com/', 'awsId'){
            def image = docker.image("01234.dkr.ecr.ap-southeast-1.amazonaws.com/tas/master-server:${env.BUILD_ID}")
            image.push()
          }

```

But what gets output in the jenkins build is the strange part

```
$ docker login -u AKIAZWB**********HET -p ******** https://01234.dkr.ecr.ap-southeast-1.amazonaws.com/
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
Error response from daemon: login attempt to https://01234.dkr.ecr.ap-southeast-1.amazonaws.com/v2/ failed with status: 401 Unauthorized

```

I remember if one runs `aws ecr get-login` the `-u` is AWS, not the access key of the credentials. So where do I get this wrong?

# Answer
I think what you are doing wrong is the way you specify the credentialID to be used.

Instead of `'awsId'` try to use `'ecr:ap-southeast-1:awsId'`

```
docker.withRegistry('https://01234.dkr.ecr.ap-southeast-1.amazonaws.com/', 'ecr:ap-southeast-1:awsId') {
    def image = docker.image("01234.dkr.ecr.ap-southeast-1.amazonaws.com/tas/master-server:${env.BUILD_ID}")
    image.push()
}

```

EDIT: Check the plugin doc
> 1 votes

# Answer
Use this instead:

```
script {
    sh "`aws ecr get-login --region ap-southeast-1 --no-include-email`"
    docker.image('01234.dkr.ecr.ap-southeast-1.amazonaws.com/<yourImage>:<yourTag>')
}

```
> 0 votes

---
Tags: jenkins-pipeline, docker-registry, aws-ecr
---


# Question
Title: Circle ci workflow job stuck in "created" when adding a required step to the workflow
```
workflows:
  version: 2
  build_deploy_test:
    jobs:
      - build:
          filters:
            branches:
              only:
                - develop
      - christest:
          requires:
            - install
          filters:
            branches:
              only: devops-docker-intial

```

With the following workflow a commit to the `devops-docker-intial` branch just results in a workflow that is 'created' - it doesn't proceed further... Why?

# Answer
> 1 votes
Due to the fact that `build` had a branch filter... Even though no error message on additional info is shown...

Hence I needed to add the branch like so:

```
workflows:
  version: 2
  build_deploy_test:
    jobs:
      - build:
          filters:
            branches:
              only:
                - develop
                - devops-docker-intial
      - christest:
          requires:
            - install
          filters:
            branches:
              only: devops-docker-intial

```

---
Tags: circleci-2.0
---


# Question
Title: docker-compose.yml - make network name configurable via environment variable
I have a docker compose file with env variables for stage specific configurations. As long as env variables are used in values in docker-compose.yml everything is fine, but the problem is with the network name, since it's specified in the tag.

```
networks:
  mynetwork.${STAGE_NAME}:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: ${STAGE_NETWORK_PREFIX}.0/24

```

Any chance to get the network name `mynetwork.${STAGE_NAME}` configurable from outside?

# Answer
> 4 votes
If you have `envsubst` installed (part or gnu `gettext`) you can use something like that:

```
export STAGE_NAME="xyz"
export STAGE_NETWORK_PREFIX="1.2.3.4"
docker-compose -f <(envsubst docker-compose.yml) ...

```

If your shell does not support process substitution, something like that would do the trick:

```
envsubst docker-compose.yml | docker-compose -f - ...

```

# Answer
> 13 votes
It is possible via network name:

```
networks:
  mynetwork:
    name: ${STAGE_NAME}

```

where mynetwork - name "inside" stack

${STAGE\_NAME} -name for other stacks/services/containers

See comment from docker capitan https://github.com/moby/moby/issues/40819#issuecomment-618726892

# Answer
> 0 votes
I didn't find a way to directly control this, but I noticed that the folder containing the docker-compose.yml is used as prefix when creating the name for the docker network. My solution was to write a wrapper script for docker-compose which creates a new folder with the name of the stage

```
TARGET=/tmp/$STAGE_NAME

mkdir -p $TARGET

ln -sf $(pwd)/docker-compose.yml $TARGET/docker-compose.yml

cd $TARGET
docker-compose "$@"
cd -

```

# Answer
> -1 votes
There is a switch -p in docker-compose which allow you to set this prefix to a custom value.

---
Tags: docker-compose, environment-variables
---


# Question
Title: Question on NGINX reverse proxy when there are services on the host and on containers
I have the following architecture, which consists of an nginx server on the host machine, and 3 urls, app1.com, app2.com, app3.com:

app1 and app2 are both in the host machine, lets say they are an HTML file on the host, on the container, there is app3 and app2.com/example url.

My question is, how can I reference the container in the nginx of the host? Since I cannot expose port 80 and 443 of the container, because the host is already using these ports, I am not sure what is the best approach to this.

I though about putting the container on a not used port, like 8999 for example, and proxying the request to this port, and blocking these ports on the firewall, so no one outside can access them. If I go with this option, does the nginx configuration inside of the containers will need the server\_name still? In the case of the app3.com/example

The other option I thougth about is using the docker socket, or even the docker0 network, but I don't know if this is viable.

An example of the nginx configuration file of the host:

```
server {
  server_name app1.com;
  location / {
    root /var/www/app1/index.html;
  }
}

server {
  server_name app2.com;
  location / {
    root /var/www/app2/index.html
  }

  location /example {
    proxy_pass http://localhost:8999;
  }
}

server {
  server_name app3.com;
  location / {
    proxy_pass http://localhost:8999;
  }
}

```

Example of the nginx configuration file of the container:

```
server {
  server_name app2.com
  location /example {
    root /var/www/app2/index.html;
  }
}

server {
  server_name app3.com;
  location / {
    root /var/www/app3/index.html;
  }
}

```

# Answer
> 1 votes
> I though about putting the container on a not used port, like 8999 for example, and proxying the request to this port, and blocking these ports on the firewall, so no one outside can access them. If I go with this option, does the nginx configuration inside of the containers will need the server\_name still?

You're thinking along the right lines. You do need the `server_name` directives in the container, since it can be accessed both by `app2.com/example` and `app3.com`.

Here's an example setup. I'll emulate an nginx on the host machine with a docker container running on the host network.

Scroll down past the code and console log for some explanations.

Here is the listing of the files I used:

```
lllamnyp@lllamnyp:~/Cloud/dev/stackexchange/devops/q11420$ tail -n +1 *

```

**==\> app1.html \<==**

```
I am app1!

```

**==\> app2\_example.html \<==**

```
I am app2 in example subpath!

```

**==\> app2.html \<==**

```
I am app2!

```

**==\> app3.html \<==**

```
I am app3!

```

**==\> container\_nginx.conf \<==**

```
server {
  server_name app2.com;
  location /example {
    root /var/www/app2/;
  }
}

server {
  server_name app3.com;
  location / {
    root /var/www/app3/;
  }
}

```

**==\> host\_nginx.conf \<==**

```
server {
  server_name app1.com;
  location / {
    root /var/www/app1/;
  }
}

server {
  server_name app2.com;
  location / {
    root /var/www/app2/;
  }

  location /example {
    proxy_pass http://localhost:8999;
    proxy_set_header Host $http_host;
  }
}

server {
  server_name app3.com;
  location / {
    proxy_pass http://localhost:8999;
    proxy_set_header Host $http_host;
  }
}

```

**==\> nginx.conf \<==**

```
user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" "$http_host" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}

```

**==\> run.sh \<==**

```
docker run --name host_nginx --network=host --rm -d \
  -v `pwd`/nginx.conf:/etc/nginx/nginx.conf \
  -v `pwd`/host_nginx.conf:/etc/nginx/conf.d/default.conf \
  -v `pwd`/app1.html:/var/www/app1/index.html \
  -v `pwd`/app2.html:/var/www/app2/index.html \
  nginx

docker run --name container_nginx -p 8999:80 --rm -d \
  -v `pwd`/nginx.conf:/etc/nginx/nginx.conf \
  -v `pwd`/container_nginx.conf:/etc/nginx/conf.d/default.conf \
  -v `pwd`/app2_example.html:/var/www/app2/example/index.html \
  -v `pwd`/app3.html:/var/www/app3/index.html \
  nginx

```

Here is the log from my console, where I am testing things out.

```
lllamnyp@lllamnyp:~/Cloud/dev/stackexchange/devops/q11420$ sudo ./run.sh
73ebc99b8fae1d18bcbc571adbab6b65eaa49f861d66f11a7490d61b4e1beb0f
9f3761ab0619255d9bde08eee70e1fb9b686b645f38d976de7c39d4c8f0ad70d
lllamnyp@lllamnyp:~/Cloud/dev/stackexchange/devops/q11420$ curl app1.com
I am app1!
lllamnyp@lllamnyp:~/Cloud/dev/stackexchange/devops/q11420$ curl app2.com
I am app2!
lllamnyp@lllamnyp:~/Cloud/dev/stackexchange/devops/q11420$ curl app3.com
I am app3!
lllamnyp@lllamnyp:~/Cloud/dev/stackexchange/devops/q11420$ curl app2.com/example
<html>
<head><title>301 Moved Permanently</title></head>
<body>
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx/1.17.10</center>
</body>
</html>
lllamnyp@lllamnyp:~/Cloud/dev/stackexchange/devops/q11420$ curl app2.com/example/
I am app2 in example subpath!
lllamnyp@lllamnyp:~/Cloud/dev/stackexchange/devops/q11420$ sudo docker logs host_nginx
127.0.0.1 - - [25/Apr/2020:15:11:15 +0000] "GET / HTTP/1.1" "app1.com" 200 11 "-" "curl/7.68.0" "-"
127.0.0.1 - - [25/Apr/2020:15:11:17 +0000] "GET / HTTP/1.1" "app2.com" 200 11 "-" "curl/7.68.0" "-"
127.0.0.1 - - [25/Apr/2020:15:11:20 +0000] "GET / HTTP/1.1" "app3.com" 200 11 "-" "curl/7.68.0" "-"
127.0.0.1 - - [25/Apr/2020:15:11:25 +0000] "GET /example HTTP/1.1" "app2.com" 301 170 "-" "curl/7.68.0" "-"
127.0.0.1 - - [25/Apr/2020:15:11:29 +0000] "GET /example/ HTTP/1.1" "app2.com" 200 30 "-" "curl/7.68.0" "-"
lllamnyp@lllamnyp:~/Cloud/dev/stackexchange/devops/q11420$ sudo docker logs container_nginx
172.17.0.1 - - [25/Apr/2020:15:11:20 +0000] "GET / HTTP/1.0" "app3.com" 200 11 "-" "curl/7.68.0" "-"
172.17.0.1 - - [25/Apr/2020:15:11:25 +0000] "GET /example HTTP/1.0" "app2.com" 301 170 "-" "curl/7.68.0" "-"
172.17.0.1 - - [25/Apr/2020:15:11:29 +0000] "GET /example/ HTTP/1.0" "app2.com" 200 30 "-" "curl/7.68.0" "-"

```

I corrected some errors in your config (missing semicolon here and there), changed the server roots to directories, rather than `index.html` and also the request for `app2.com/example` would request `/var/www/app2/example/index.html` so pay close attention to the way in which I mounted the files when starting up the containers in `./run.sh`. Finally, it was necessary to do `proxy_set_header Host $http_host;` in the host nginx config, so that the requested `Host` header gets correctly relayed to the containerized nginx and both app2 and app3 work correctly.

---
Tags: docker, nginx
---


# Question
Title: GKE: Sharing the same filesystem across pods
I'm quite new and try to get my head around kubernetes and GKE so here it goes:

I would like an application to write data to a persistent storage.

If I'd scale up, or down, or a pod dies, I'd like this persistent storage to survive.

Also, the same data should be available to different pods.

How do I achieve this?

The data are images, so storing them in a database could be a valid solution for this case, but I wondered whether - if data is big - there are also solutions with filesystems to achieve this...

Thanks for answering,

S.

# Answer
I think it's a pretty n00b question :(

I suppose you'd need a pod which manages the filesystem, and make it available to the other pods which need the functionality to store data on it...

Br,

S.
> 1 votes

---
Tags: storage, google-cloud-storage
---


title: AWS: Onboarding on premise instance

text:
# Question
Title: AWS: Onboarding on premise instance
Is there a way to onboard the Raspberrypi device in AWS. So that the same device can be managed using ec2 console and it can seamlessly work with the rest of AWS services?

I am just an experimental user, I don't need much heavy computer but use AWS to host my website and blogs, etc.

# Answer
> 2 votes
AWS console is for managing AWS resources, which, arguably, your Raspberry Pi is not.

Some services can work with non-AWS resources. For example you can install *System manager agent* (though not sure if there is a RPi version) on on-prem servers.

Alternatively you can install **AWS Greengrass for Raspberry Pi** that gives it *some* AWS capabilities.

Hope that helps :)

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


# Question
Title: Managed MySQL cluster - similar solution for a private cloud
Is it possible to build a similar solution to managed MySQL cluster on a private cloud (VMware vSphere / Hyper V). Even with Kubernetes. A solution which supports auto-scaling, auto-upgrade, multi-master and similar to the largest public clouds offerings.

# Answer
There shouldn't be any reason why you can't. I think that the issue would be in getting the memory management correct on the host. The orchestration would be the same.

Here's some resources:
> 1 votes

---
Tags: kubernetes, mysql, vmware
---


# Question
Title: Apache Airflow federation - observe remote dag in full detail?
We have numerous airflow instances running in different organizations/teams around the company. While we have built a highly scaleable centralized airflow service, we do have cases where we need to depend on another airflow instance to run a dag.

Our DevOps team often gets tasked with running larger orchestrations across teams, and we prefer to keep a highly detailed view of all tasks, even if they are in a remote airflow.

Is there any good way to monitor, with full fidelity, all of the tasks in a remote airflow? Something similar to the sub-dag operator for a remote airflow would be sufficient.

# Answer
I spent a long time on this problem and made 2 custom solutions as nothing out of the box exists.

Both steps require you to either use both the experimental and the extra plugin API **or** to have access to the remote database.

At that point, basically either:

* Make a GUI plugin on a separate page that hits the APIs and shows all tasks (list exec dates, list tasks in exec date, get status of each).
* Make python operator steps in your dag to call out to the state of the remote dag steps with the same name. It's hard to reflect anything outside of running/done though as you need your step to keep checking in case the remote end restarts the step/tries again.

The APIs are slow, so this isn't fun. I'd recommend going for the DB if you have the option.

Airflow 2.0 will fix the APIs apparently, and then this may be a lot easier.
> 1 votes

---
Tags: orchestration, apache-airflow
---


title: Continuous deployment

text:
# Question
Title: Continuous deployment
I have a nodejs application using expressjs. This server is handing a website built on vuejs, an application using angular and another angular app. Everything is working and I deployed to AWS eb using a pipeline. The problem is when a website change is made I build it and commit the change to AWS code commit.

Is there a way to make this automatic?

Should I keep all projects in the same repo?

What I want is: website change -\> commit -\> build website only -\> push to AWS.

The only solution I can think of is to rebuild the 3 projects every time.

# Answer
> 1 votes
I would suggest adding a job that checks changes in the latest commit and build only that service where some files have been changed.

---
Tags: continuous-integration, git, continuous-deployment, continuous-delivery, aws-codepipeline
---


# Question
Title: Startup of ECS Fargate task fails with ResourceInitializationError mount.nfs4 Connection timed out
When starting up an Amazon ECS task with launch type FARGATE it fails with the following reason:

```
ResourceInitializationError: failed to invoke EFS utils commands to set up EFS volumes: command failed with 32: failed to execute command to invoke EFS utils: mount.nfs4:

Connection timed out

```

The fargate task is a docker image that needs to mount EFS as persistent storage.

Why is the connection timing out?

# Answer
Underlying reason:

The ECS service's network access security group did not have permission to access EFS.

Solution:

Add an inbound rule for type `NFS` in the security group as described in this tutorial: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/tutorial-efs-volumes.html#efs-security-group
> 5 votes

---
Tags: amazon-ecs, fargate, amazon-efs
---


# Question
Title: kubectl create deployment not has the option containerPort
When I execute `kubectl create deployment nginx --image nginx --dry-run=client -o yaml` it does not have options `--port` or `--containerPort`. My yaml is:

```
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: nginx
  name: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx
        name: nginx
        resources: {}
status: {}

```

Is there a way to generate yaml with the `containerPort` option?

# Answer
> 2 votes
From the kubernetes docs I see this example:

```
$ echo 'apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: deployment-example
spec:
  replicas: 3
  revisionHistoryLimit: 10
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.11
        ports:
        - containerPort: 80
' | kubectl replace -f -

```

So under your `containers` entry you should be able to add:

```
        ports:
        - containerPort: 80

```

Is that what you had in mind or, at least, good enough? You seem to want this as a command line option for the `kubectl` command and I don't see anything that indicates this is possible.

---
Tags: kubernetes, kubectl
---


# Question
Title: Looking at a Career jump into DevOps and advice or suggested reading
I've been in various facets of Software development over the past 10+ years. I started in the development side of the Application Lifecycle Management(= ALM) cycle, and more recently I've been working in the QA side of ALM.

One thing that has consistently bothered me was all the different companies that I've worked for tried to embrace an effective ALM process but in the end it usually turned out to be a half-baked implementation of a scrum methodology that had all the different team leads debating about the right and wrong ways to implement ALM processes.

I've been currently researching DevOps in hopes that I can shift my career to a direction that will allow me to better contribute to a companies ALM process.

I have quite a bit of experience in Dev, QA, and General IT but I wouldn't consider myself an absolute expert in either area.

Any suggestions, advice, recommended reading, etc?

If you recommend a book could you include the ISBN number (it's easier to search for it that way).

# Answer
> 5 votes
I do not think that there is a single correct piece of advice for such a broad question, but here are my thoughts your situation:

**As a starting point** look at your current workflow, processes, and technologies being used at the company and then research some tools *(Jenkins, Kubernetes, Docker, Grafana, Ansible, Kubana etc)* or techniques(writing your own scripts or programs) that might be useful to your company or any projects you are working on.

I would also suggest maybe attending local DevOps meetups or talks in your area for more exposure.

# Answer
> 5 votes
Google's SRE book would be a good start.

I would also pick a configuration management system like or and practice with it. Maybe use it to setup your next desktop or server.

# Answer
> 1 votes
The Phoenix Project is one of the best book to read about DevOps and their is one very interesting community driven website devopsuniversity.org they are also updating interesting material on DevOps to start with.

---
Tags: culture, learning
---


# Question
Title: Trigger downstream pipeline job for the branch via from upstream freestyle job
I have an upstream freestyle job and a downstream pipeline job.

The freestyle job is triggered via a gitHub webhook to run whenever code is pushed to gitHub branch.

The freestyle job should capture the branch name and pass to the pipeline job and should trigger the build for that particular branch.

How to pass the branch name to the pipeline job dynamically?

# Answer
> 1 votes
The "Add Parameters" can help you. You should set up your downstream pipeline with "GIT\_BRANCH" parameter to build with that branch, and transfer it from this upstream job.

# Answer
> 1 votes
Can't tell you why this does not work, I'm not using the Jenkins UI for build configuration anymore. I guess the Jenkins UI is blocking you because it does not recognize tha `$GIT_BRANCH` is a variable.

We do exactly what you are trying with a script-step in the pipeline, and that works:

```
stage('Trigger downstream job') {
   steps {
      script {
         build(job: 'SomeJob/' + env.GIT_BRANCH.replaceAll('/', '%2F'),
               parameters: [...],
               propagate: true,
               wait: true)
      }
   }
}

```

Note that `/` in the branchname must be escaped.

So I recommend to rewrite your job with a Jenkinsfile :-)

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