# Question
Title: How to have Ansible move a microservice?
I am working with a microservices application that is using Ansible to deploy to a fleet of VMs. We have different numbers of replicas of each microservice type running across the VM fleet. Deployments are working fine using a single deploy playbook, passing it extra variables to say which service to install, and giving naming it a group of hosts in the inventory to run against.

Occasionally we need to move microservices between hosts to rebalance load. This isn't clean with how we have set up Ansible. Moving one microservice instance means adding one new host entry, and removing one old host entry, from the inventory group. The new instance is installed but no logic will run against the removed host. We have to run another playbook to uninstall the service from the removed host.

I am looking for a way to reorganize ansible so that it will quickly move a microservice. I am thinking that we should use a single inventory group of all hosts and use a list variable to say which hosts a microservice runs on. A custom fact can be set when a service is installed. The install task can check the fact and that the current host is in the list. The uninstall task can also check the fact and that the current host isn't in the list. Is this the right way to organise the logic or is there a better way?

# Answer
> 0 votes
I have created a demo with a role that can install many springboot microservices on a fleet of VMs where you name a subset of the VMs where you want to place each service. The playbook can then run on all hosts, compute whether each service should be on each host, and will either run the install.yaml or uninstall.yml tasks.

To install two of the same microservices with different runtime args you play something like:

```
roles:
    - {
      role: "ansible-role-springboot",
      sb_app_name: "microservices-registration",
      sb_app_group_id: "org.springframework.samples.service.service",
      sb_app_artifact_id: "microservices-demo",
      sb_app_version: "2.0.0.RELEASE",
      sb_app_run_args: '"registration 8082"',
      sb_app_healthcheck_urls: [
        "http://localhost:8082/actuator/health"
      ],
      **sb_hosts: [
        "my-test-vm"
      ]**
    }
    - {
      role: "ansible-role-springboot",
      sb_app_name: "microservices-web",
      sb_app_group_id: "org.springframework.samples.service.service",
      sb_app_artifact_id: "microservices-demo",
      sb_app_version: "2.0.1.RELEASE",
      sb_app_run_args: '"web 8083"',
      sb_app_healthcheck_urls: [
        "http://localhost:8083/actuator/health"
      ],
      **sb_hosts: [
        "my-test-vm"
      ]**
    }

```

The role is based upon orachide/ansible-role-springboot which seems very comprehensive. The new bit is in bold which is simply a list of host that should run the microservice.

Normally we would expect to use different artefact ids and versions each time we apply the role. In the example above, it is running an official springboot microservices mega jar that takes different `RUN_AS` args to run as different services. That seems a bit odd and not something I would recommend yet the role is agnostic to such details.

What thing that the original role requires is that you use an executable jar file:

```
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <executable>true</executable>
            </configuration>
        </plugin>

```

It role will create a symlink to that executable and create an environment files to run it and all that good stuff.

The modifications that I made were quite simple as the original role has logic to install or uninstall based on `sb_app_state`:

```
- import_tasks: install.yml
  when: >
        sb_app_state == 'present'

- import_tasks: uninstall.yml
  when: >
        sb_app_state == 'absent'

```

So it was simply a matter of adding some logic to check whether the current hostname is in the `sb_hosts` list then update the value of `sb_app_state` as appropriate. That is done with a single line change.

The demo codebase uses test kitchen ansible with testinfra to unit test that the playbook works. Getting that working was well worth the effort to do automated acceptance tests of the playbook logic.

---
Tags: ansible, microservices
---


title: Code splitting practice using CDN

text:
# Question
Title: Code splitting practice using CDN
I have a web frontend app uses code splitting to reduce the individual file size. And it's distributed on a CDN and works most of the time.

A problem occurs when we update the project at any time. Assume that our project consists of following files:

* `index.html`
* `main.1ef1a.js`(where `1ef1a`, as well as `bce31` in the next line, is content hash)
* `on-demand.bce31.js`

`index.html` imports `main.[content-hash].js` and `main.[content-hash].js` loads `on-demand.bce31.js` on demand.

The error scenario is a user loads our page just before our update and he/she gets `index.html` and `main.1ef1a.js` and browser caches them. And then our update happens: we replace the files, flush the CDN, and following files are get distributed:

* `index.html` now imports a new version of `main.js`
* `main.2a3db.js`
* `on-demand.5231f.js`

Then user does something that triggers the loading of `on-demand.js`, while since his/her `main.js` is old, he/she requests `on-demand.bce31.js`, which no longer exists, and then the page crashes.

He/she is a very nice user with patience and tries a refresh, but the browser serves the cached `index.html` and `main.js` again and he/she cannot get ouside the loop.

We cannot assume our users to have certain knowledge to perform a "Clean cache and force reload", all we get are disappointed users who think our website sucks.

I think code splitting and CDN are both widely used techniques and there should be some nice solution that I'm missing. And what is that ?

# Answer
> 4 votes
Your main problem is that you're flushing the CDN when you're deploying a new set of artefacts, which will effectively ruin anything still in progress (whatever its state). You should add the new artefact versions and leave the older ones in place, at least for as long as your published cache lifespan for the top `index.html` file is.

This way even if users look at an older (cached) version of the page which references other older version artifacts they'll still be able to download them (users have no clue that a new version is available as the cached version is immediately served as long as it's not expired). And whenever the cache expires users will get the new version of the top page, with the references to the new artefact versions.

---
Tags: cdn
---


# Question
Title: Rollup status from task to story to feature in Azure Devops?
Are there any extensions that let you rollup issue status across a hierarchy?

For example, if I have a story where all it's tasks go to Resolved, then the story is set automatically to Resolved?

Likewise, if I have a story where at least one of the tasks go to Active, the story is set to Active, then the story is set to Active?

Ideally, it would do this across a hierarchy, from task, to story, to feature, etc.

Currently, I don't see any extensions that do this.

# Answer
> 1 votes
You may try TFS Aggregator (Web Service). If you or your team have experience with C#, you may try the console project that I\`ve developed: Automation of state changing.

---
Tags: azure-devops
---


# Question
Title: How to build windows image on azure dev ops hosted agent
The host agent pool on azure-devops to build windows container, `Hosted Windows Container` is running Windows Server version 1803.

But I want to deploy on Windows Server 2019, so instead of using Microsoft `:1803` images, I'm building from images tagged `:ltsc2019`.

How can I build my `:ltsc2019` images on azure-devops?

# Answer
> 1 votes
## EDIT

Microsoft added a new hosted agent: `Hosted Windows 2019 with VS 2019`.

So you should use this image to build for `windows-1809` or `windows-2019`

Source : https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/hosted?view=azure-devops&tabs=yaml#use-a-microsoft-hosted-agent

---

# Old answer:

FWIW, I ended up creating a windows server 2019 vm on azure to act as a build agent.

Could not manage to build 2019 image in any of the hosted agent pools.

---
Tags: docker, containers, windows, azure-devops, build-pipeline
---


# Question
Title: Looking for Ansible equivalent method to yml Anchors, Aliases, when using include file
Using Ansible with the **aci\_rest** module, requires the authentication parameters (*hostname, username, password, method, validate\_certs*) to be defined in every task e.g.

```
aci_rest:
  hostname: "{{ inventory_hostname }}"
  username: "{{ apic_username }}"
  password: "{{ apic_password }}"
  method: post
  validate_certs: no
  path: /api/node/mo/uni/controller/nodeidentpol.json
  method: post
  ...etc

```

The YML Anchors, Aliases syntax works perfectly fine within one file.

```
- aci_rest:
    <<: *aci_login
    path: /api/node/mo/uni/controller/nodeidentpol.json
    method: post
    ...etc

```

However not when variables and tasks are in different files using any of these functions:

```
vars_files:
include_tasks:
include_vars:

```

The full playbook has 70+ tasks with the authentication info repeated every time. I have not been able to find a way to not use repeat code. Is there a way to do this similar to yml alias?

# Answer
There is module\_defaults playbook-level option:

```
- hosts: localhost
  module_defaults:
    file:
      owner: root
      group: root
      mode: 0755
  tasks:
    - file:
        state: touch
        path: /tmp/file1
    - file:
        state: touch
        path: /tmp/file2

```
> 1 votes

---
Tags: ansible
---


# Question
Title: How do you limit access to the production environment in the company you work for?
In the company I work for, devops engineers (currently only 2 members, who are me and another coworker) are the only people who have access to the production database.

So when any other developers need to execute a MySQL query on the production database. They would send the query to the 2 engineers to let them execute it.

Here are the situations when we need to execute commands to the production database:

1. The database contains corrupted data, which produce bugs. They execute commands to fix the bugs.
2. A bug is reported. And they want to see the current values inside the database.
3. One of our customers wants to modify his/her data. But our web application doesn't have the ability to do the modification. So we have to send MySQL commands directly to the database to complete the customer's requirement.
4. The QA team created test accounts on the production environment. And they want to change the account's status so that they can do other tests.

This creates a lot of interruptions for me and the other coworker. When we develop programs during the daytime, we often have to switch context just to execute some queries.

I don't think this is a good architecture for the company. How do you control the permissions to the production environment in your company?

Our production database consists of sensitive customer information. If the data were leaked out, our company might be fined for millions of dollars.

# Answer
If your question is how to manage database changes consider something like Flyway. This lets you control your changes via tracked config files in your repository and apply them via an automated & controlled process - use your normal code review & promotion steps.

If the question is "how do I get devs to stop bugging me to run arbitrary SQL commands" then you may want to consider scripting out a way to automate it or giving them a 3rd party UI to use with an account that's locked down to prevent changes & restricts them from seeing any sensitive tables. YMMV depending on the layout of your DB.
> 5 votes

# Answer
You could embed database schema and data changes into source code control by using a concept called database migrations. These can then be executed on dev and staging environments as part of a partially automated deployment process.

For example in my environment (PHP Web application), I am using Doctrine Schema for schema updates, Yii2 migrations for data changes. The respective commands are part of a 7 line bash script that runs all necessary commands to deploy a change in each environment
> 4 votes

# Answer
I see a first problem, DevOps is about building teams able to handle an application from build to exploitation.
So your devs should have access to the databases, you quoted various cases which are the reality for a lot of people and the major drawback which is turning you and your colleague in a bottleneck as well as impeding your own work.

Other answers address well the schema change or planned changed which should indeed be integrated as part as the application delivery process, but they don't allow to quickly fix the live access need, when a dev may need to dump the DB to understand what caused the bug and how to fix it for exemple.

Things like ProxySQL you already quoted in a comment could be ok for MySQL databases, just configuring MySQL to log things could be a good approach also, MySQL offers a commercial audit plugin which may answer the problem of letting your devs access the database and fulfill your CISO requirements of keeping track of what is done.

If you have more than just Mysql DB and need to audit their access, configuring each system to audit log users actions and not application actions could be cumbersome. Keeping the things closed could be even worse, one dev will one day integrate a DB shell in an application to circumvent this road block and it will eventually go live in production without proper access control and expose all datas, I strongly advise you to ask your company to review this policy.

There's one commercial solution that I know which can help (and allow auditing more than just DB requests) which is strongDM, it also allow to audit ssh and rdp sessions, as if your devs needs access to DB, they probably also need access to the machines hosting the applications for debugging purposes.
> 4 votes

# Answer
> ... me and another coworker ... are the only people who have access to the production database.

That's a good starting position.
All too often, DBA's find themselves trying to close the stable door after the horse has run off.

> So when any other developers need to execute a MySQL query on the production database ...

Question:
Why are Developers running *anything* against the Production database?

> How do you control the permissions to the production environment in your company?

Role-Based access control.

Users are given access to each database as and when their job role requires it and Roles are used to give them access to the tables within each database. The process by which these accounts are created and roles granted is centrally-managed and strictly audited.

Developers should **never** have "hands-on", update access outside of their Development databases. *Everything* else should be scripted, tested, audited and released through pre-prepared, controlled (and, preferably, automated) channels.
> 1 votes

---
Tags: permissions
---


# Question
Title: Maven dependencies that are downloaded not available in JFrog Artifactory server
I have the following repositories structure created in my newly installed Artifactory instance. And we are using this artifactory instance to store the Maven artifacts. Most of our projects are in Java and we use Maven as the build tool. As this is a new installation our .m2 repository cache is empty and when we did our initial 'mvn compile' it has downloaded all the dependencies from Maven Central repository and placed the dependencies under .m2 cache but not in our artifactory instance.

According to our understanding, we thought if the dependencies are not available in Artifactory server then it downloads from a public repository and then it keeps a copy in Artifactory server and also in a local .m2 cache. Is that how it works? When the dependencies are downloaded from public repository we also wanted to have that available in our artifactory server so that when a Maven is installed in a new machine then it should get that dependency from our Artifactory server itself. Is that possible?

Here's the list of our repositories:

```
Local
 - wellows
Remote
 - wellows-remote
Virtual
 - wellows-virtual

```

# Answer
> 2 votes
In order Artifactory to cache your dependencies, you need to retrieve them from Artifactory. Once you use your virtual repository, which contains the Maven Central remote, Artifactory will download the dependencies from Maven Central and will cache them for the future use.

So, here's what you need to do in order to populate Artifactory with your dependencies:

1. Make sure that your virtual repository contains Maven Central or JCenter remotes.
2. Configure your Maven to work with Artifactory (The "Set Me Up" button in the Artifactory UI)
3. Delete the `~/.m2/repositories` cache
4. Run your build again.

---
Tags: maven, java, artifactory
---


# Question
Title: TravisCI did not run after adding more configuration to .travis.yml file
I added some AWS keys to my `.travis.yml` file so that it would deploy my application over to ElasticBeanstalk, but after I committed the changes to the file and pushed to master, nothing happened.

I thought perhaps I needed to restart build. This added my AWS keys, but no installation of deployment dependencies as I had expected and no deployment to AWS.

Not sure what happened here. Did I not wait long enough for TravisCI to start the new build?

This is my `.travis.yml` file:

```
sudo: required
services:
  - docker

before_install:
  - docker build -t danale/project-name -f Dockerfile.dev .

script:
  - docker run danale/project-name npm run test -- --coverage

  deploy:
    provider: elasticbeanstalk
    region: "us-east-1"
    app: "project-name"
    env: "ProjectName-env"
    bucket_name: "elasticbeanstalk-us-east-1-123456789"
    bucket_path: "project-name"
    on:
      branch: master
    access_key_id: $AWS_ACCESS_KEY
    secret_access_key:
      secure: "$AWS_SECRET_KEY"

```

I conducted a `git add . && git commit -m "added travis deploy script" && git push origin master`

No deployment afterwards. I don't see where I missed a step here: https://docs.travis-ci.com/user/deployment/elasticbeanstalk/

# Answer
One of the headaches of `.yml` files is the indentation. So the parse error I was getting in the Request tab was saying no newline added. I was not clear whether that meant it needed a new line or was missing a new line, but by running: `wc -l .travis.yml` I was able to detect that it was not outputting the correct number of lines.

I tried about five different ways to format the `.yml` file allowing it to keep me focused towards the end of the files line number where the error was pointing towards.

I happen to look up and realized the beginning of the deploy: script was not properly aligned, so I adjusted with a shift+tab and after I got it properly aligned, TravisCI recognized my changes and properly ran the script and successfully deployed the application to Elasticbeanstalk.
> 1 votes

---
Tags: amazon-web-services, git, github, travis-ci
---


title: Are AWS Boto3 calls asynchronous?

text:
# Question
Title: Are AWS Boto3 calls asynchronous?
In the API documentation for Apache Cloud Stack for example, they put an (A) to designate asynchronous API calls.

In the Boto3 - Python client API for AWS - documentation as I can't see anything like this - so my question is whether its API is asynchronous or not.

# Answer
Boto3 is a client for AWS API, so by definition it doesn't handle the synchronous or asynchronous behavior of the API call, that's the API endpoint which define that.

You can safely assume that any API endpoint marked as asynchronous will be asynchronous in any API client. Some SDK implement methods to wait for those asynchronous calls, some don't and you need to write your own handling (usually polling regularly the state) if you need to wait the end of a task started by an API call (creating a CloudFormation stack for exemple).
> 4 votes

---
Tags: amazon-web-services, python, api
---


# Question
Title: How to securely pass sensitive data to EC2 Spot instances?
Right now, we only use EC2 on-demand instances, and we provision sensitive data (credentials, private keys, etc.) on the instances' EBS which are encrypted with a KMS key.

My understanding is that I have a few ways to pass those secret data to Spot instances:

* Burn them in an encrypted AMI (but then, what about host-specific stuff, like SSH server private keys?)
* Pass them as UserData when we call RunInstances (but then we would need to encrypt those data, and decrypt them with a secret burnt in the AMI)
* Use Secrets Manager, but that could quickly cost a lot...
* Use Parameter Store, and encrypt the payload with a KMS key (1 shared key for shared data + 1 key per node for node specific data?)

And I am not sure I could individually identify spot instances?

Am I missing something there? How do you solve those challenges?

# Answer
> 3 votes
When you're running ephemeral workloads like you would on a spot instance the best bet, if you don't want to bake an ami, is going to be a secret store of some kind.

The two most common methods I've seen for doing this are:

1. If your provisioning tool (terraform, cloudformation, salt cloud) allows it then you can create a kms key and use it to encrypt secrets in user data. Once the instance has started it can decrypt them using that key.
2. You can use a secret store like you mentioned. You said that AWS Secrets Manager would get pricey so you're probably going to want to use Vault. It's not *that* hard to set up and can use IAM permissions to allow your instances access to secrets. Using it also opens other avenues to doing secret storage right.

---
Tags: amazon-ec2, security, devsecops
---


title: How to change Jenkins' port to 80?

text:
# Question
Title: How to change Jenkins' port to 80?
I installed Jenkins on a Ubuntu 18.04 ec2 instance by following its official guide.

I want to change Jenkins from port 8080 (default) to port 80.

According to its official document:

> If your /etc/init.d/jenkins file fails to start Jenkins, edit the /etc/default/jenkins to replace the line ----HTTP\_PORT=8080---- with ----HTTP\_PORT=8081---- Here, "8081" was chosen but you can put another port available.

I managed to changed it to port 8081 but when I used port 80, it simply doesn't work:

`curl -i localhost:80` returns `connection refused`

`sudo systemctl status jenkins` gives

```
jenkins.service - LSB: Start Jenkins at boot time
   Loaded: loaded (/etc/init.d/jenkins; generated)
   Active: active (exited) since Thu 2019-02-21 08:14:55 UTC; 4min 12s ago
     Docs: man:systemd-sysv-generator(8)
  Process: 6143 ExecStop=/etc/init.d/jenkins stop (code=exited, status=0/SUCCESS)
  Process: 6212 ExecStart=/etc/init.d/jenkins start (code=exited, status=0/SUCCESS)

Feb 21 08:14:53 ip-172-31-11-10 systemd[1]: Starting LSB: Start Jenkins at boot time...
Feb 21 08:14:53 ip-172-31-11-10 jenkins[6212]: Correct java version found
Feb 21 08:14:53 ip-172-31-11-10 jenkins[6212]:  * Starting Jenkins Automation Server jenkins
Feb 21 08:14:53 ip-172-31-11-10 su[6257]: Successful su for jenkins by root
Feb 21 08:14:53 ip-172-31-11-10 su[6257]: + ??? root:jenkins
Feb 21 08:14:53 ip-172-31-11-10 su[6257]: pam_unix(su:session): session opened for user jenkins by (uid=0)
Feb 21 08:14:54 ip-172-31-11-10 su[6257]: pam_unix(su:session): session closed for user jenkins
Feb 21 08:14:55 ip-172-31-11-10 jenkins[6212]:    ...done.
Feb 21 08:14:55 ip-172-31-11-10 systemd[1]: Started LSB: Start Jenkins at boot time.

```

I am sure nothing runs on port 80.

What am I doing wrong?

# Answer
Assuming you are okay with moving your Jenkins(and settings) to a docker environment, you can do the following. This would give you the advantage to change ports(and manage jenkins) with greater ease in the future without ever having to touch IP tables or load balancers.

Host your Jenkins on a docker container and map the port 80 on your docker host daemon to 8080 on the container.

You can find the latest jenkins docker image here - https://hub.docker.com/\_/jenkins

Install docker daemon and download the image using `docker pull jenkins`

You can use docker run command to start jenkins along with the -p argument to supply port values.

For instance, you are hosting your docker daemon on 10.10.169.69, then you use this to start Jenkins `docker run -t container_tag -p 80:8080 image_name`

And then to browse jenkins, use http://10.10.169.69:80/
> 1 votes

---
Tags: jenkins
---


title: Docker machine connection with https

text:
# Question
Title: Docker machine connection with https
I am new to Docker. I installed Docker tool box on my Windows machine.

Using pom.xml I want to generate docker image . pom.xml:-

```

<plugin>
    <groupId>com.spotify</groupId>
    <artifactId>docker-maven-plugin</artifactId>
    <version>0.4.11</version>
    <configuration>
        <repository>${docker.image.prefix}/${project.artifactId}</repository>
        <imageName>${docker.image.prefix}/${project.artifactId}</imageName>
        <dockerDirectory>${project.basedir}/src/docker</dockerDirectory>
        <dockerHost>https://192.168.99.102:2376</dockerHost>
        <dockerCertPath>C:/Users/shridhar/.docker/machine/machines/default</dockerCertPath>
        <forceTags>true</forceTags>
        <imageTags>
            <imageTag>${projectVersion}</imageTag>
            <imageTag>latest</imageTag>
        </imageTags>

        <!-- push the image on docker hub -->
        <serverId>docker-hub</serverId>
        <registryUrl>https://hub.docker.com</registryUrl>
        <resources>
            <resource>
                <!-- war file locaion wheere war should be present (copied) -->
                <targetPath>/   </targetPath>
                <directory>${project.build.directory}</directory>
                <include>${project.build.finalName}.war</include>
            </resource>
        </resources>
    </configuration>
</plugin>

```

Docker machine details

```
$ env | grep 'DOCKER'

```

```
DOCKER_HOST=tcp://192.168.99.102:2376
DOCKER_MACHINE_NAME=default
DOCKER_TLS_VERIFY=1
DOCKER_TOOLBOX_INSTALL_PATH=C:\Program Files\Docker Toolbox
DOCKER_CERT_PATH=C:\Users\shridhar\.docker\machine\machines\default

```

I get the below exception:

```
Caused by: com.spotify.docker.client.exceptions.DockerException: java.util.concurrent.ExecutionException: com.spotify.docker.client.shaded.javax.ws.rs.ProcessingException: org.apache.http.client.ClientProtocolException

```

If I make tcp connection

```
<dockerHost>tcp://192.168.99.102:2376</dockerHost>

```

then I get below exception:

```
Caused by: java.lang.IllegalArgumentException: An HTTPS URI for DOCKER_HOST must be provided to use Docker client certificates

```

What changes do I have to make to build image sucessfully?

# Answer
Considering you say you want to build an image (and not push it to Docker hub or wherever):

docker-maven-plugin project recommends using dockerfile-maven for new projects, as the former

> \[...\] ultimately led to a lot of unnecessary confusion with our users that stemmed from introducing extra abstractions and a need for configuration on top of what Docker is providing.

The dockerfile-maven `README` should get you started, with both a sample `Dockerfile` and the relevant `plugin` section for your `pom.xml`
> 1 votes

---
Tags: docker, maven
---


# Question
Title: What means “system engineer practicing DevOps”?
In the comments section of this answer, it’s explained that the asker is a “(system) engineer practicing DevOps” not a DevOps engineer, and this it is an “important distinction” not often understood.

So, what makes a DevOps Engineer NOT a DevOp Engineer? What is the distinction between a System Engineer and DevOps Engineer that is not often understood?

# Answer
What the comment means is that DevOps is a way of working, a culture if you will, not a job title. There are plenty of blog posts about it.

While they have a point, one could also argue that Cubism is a way of painting, but "cubist painter" is still perfectly valid.

This is a potentially long and opinionated discussion, which is out of scope of this forum.

The point is, the definition of DevOps is too lacking on specifics about what exactly the person practicing it does and what kind of tools they use to do it to be of any actual use as a job title. Which is why it is often misunderstood and misused. And there is (almost?) always a better title to describe the job.

For example, if your job consists of solely setting up pipelines in Jenkins, then you might get slapped with the title "DevOps Engineer". However:

* A job that specialized would be contrary to the idea of DevOps in the first place.
* "Jenkins specialist" is a more apt title. Just an example, there are better names for it.

The title is avoided by most companies these days, often replaced by "Automation Engineer". Which, while still vague, it is less so then DevOps Engineer.

Going back to the specifics of the comment, many times the people that installed Jenkins (and the like) in a company were the Systems Engineers. And they probably also explained how it works to other people in the company, maybe even used the term DevOps to explain the philosophy behind it. Which is why the two are often confused. "The guy that takes care of Jenkins? Oh, you mean the DevOps guy? Yeah, DevOps Engineer". No, he's a Systems Engineer practicing DevOps. If nothing else, he should know a lot more than just Jenkins.
> 4 votes

# Answer
Most companies adopting DevOps practices often create teams with a combination of software engineers and operations engineers, thus creating DevOps teams. Although, i don't completely agree with this approach, I've heard it does help for adopting DevOps in large organizations. The responsibility for both these different (yet similar in many areas) guys is to embrace the DevOps culture and work in the best interest to make up for the missing skills in the other guy.

**For the systems engineer, this would mean that you will apply your current skill set in systems administration for managing infrastructure in a way that's it's helpful for the software engineers to making automated programs for creating processes for efficiently building and releasing software.**

Having said that, the efforts for both the guys should be to share each others' skills to become a beacon for the rest of the organization to adopt a stable DevOps culture.

In an ideal world, everyone in the Product development and operations should be practicing DevOps.

Hope this clarifies your query to some extent.
> 2 votes

---
Tags: culture
---


title: Process auditing in containers

text:
# Question
Title: Process auditing in containers
I've read numerous articles on this going back to 2013, but what I wasn't able to ascertain is whether a reliable method has yet been devised for auditing processes inside a container. This question applies primarily to Linux, as I'm not very familiar with containerization on other platforms.

The problem is essentially this: How to track operations such as Linux system calls back to the user who created the container?

With Docker, that information is lost because the container is started by a daemon, and Docker doesn't have an authentication mechanism in place for identifying the user.

Podman takes the approach of creating a container as a process fork, rather than using a client/daemon, which preserves the loginuid, but what about across a cluster.

Kubernetes has auditing functionality, but I haven't been able to determine from the documentation whether that applies to processes running in containers, or only to K8s API calls.

It's seems like it would be possible to do this by:

1 - Require a user to authenticate when starting a container.

2 - Send the user name when starting the container on each node.

3 - Preserve the user ID in a process attribute.

For `2`, to work, the user would have to be known to each host, and not just the container daemon.

A trivial case of `3`, would be for the user in the container to have the same UID, and the authorization stage could enforce that. But that's pretty limiting.

Has anyone managed to address this successfully, or is it still an open issue? Either a global solution, or for a particular containerization technology/orchestrator.

Here are some links regarding proposals for implementing this in the kernel:

# Answer
> 1 votes
I think there is a way to do this on docker:

> As of Docker 1.10 User Namespaces are supported directly by the docker daemon. This feature allows for the root user in a container to be mapped to a **non uid-0** user outside the container, which can help to mitigate the risks of container breakout. This facility is available but not enabled by default.

You can map the root user inside docker container to specific user from the host machine (uid).

---
Tags: docker, kubernetes, containers, audit
---


# Question
Title: How to stop a container dying at the end of an execution?
I'm running git-all-secrets over our organisation to ensure we have nothing exposed. I'm doing this using:

```
sudo docker run --rm -it abhartiya/tools_gitallsecrets -org <org> -output /root/output.txt -thogEntropy -token <githubtoken>

```

I've monitored the events for this repository, and after the command completes, the following events fire:

```
2019-02-21T13:01:36.386539368Z container die cc479e7ac878f39c1e555eea1cbc9105dc06e21a526639975cd15f031297ab23 (exitCode=0, image=abhartiya/tools_gitallsecrets, name=inspiring_bell)
2019-02-21T13:01:36.602243215Z network disconnect 26b5a225be28b13153e587c4d1464361957ac899bc1a4152c6ae5aacc3229a0f (container=cc479e7ac878f39c1e555eea1cbc9105dc06e21a526639975cd15f031297ab23, name=bridge, type=bridge)
2019-02-21T13:01:37.235130059Z container destroy cc479e7ac878f39c1e555eea1cbc9105dc06e21a526639975cd15f031297ab23 (image=abhartiya/tools_gitallsecrets, name=inspiring_bell)

```

Since the container is then destroyed, I can't then copy the file locally after exection by using:

```
a@ubuntu-s-2v-2-01:~$ sudo docker cp cc479e7ac878:/root/output.txt ./output.txt                                                                                │ 0 -rw-r--r-- 1 codingo codingo     0 Dec 19 04:49 .sudo_as_admin_successful
Error: No such container:path: cc479e7ac878:/root/output.txt

```

I'm still new to docker, so I'm not sure what the solution to my problem is - but how can I have the docker contain

# Answer
> 3 votes
Option `--rm` tells Docker explicitly to remove the container after the (main) command finished. Just leave it out.

Note that none of the examples contain this option; they only use it for `-help`.

As an alternative (which lets you keep `--rm`), you can tell Docker to mount a volume at `/root`. Volumes persist after the containers mounting them go away, so you can access the data written there. However, for your purposes here, a simple bind mount is quite enough; add

```
-v .:/root

```

to have it write the output file to the current (host) directory. You may have to adjust this if `/root` is used heavily; you probably want to use a previously empty directory on both sides.

# Answer
> 0 votes
Docker container dies when there is no process run in it. If you want a docker not to die you need a process to keep runing, This can be any process even bash process (/bin/bash).

Usually a docker container can be re-started with `docker start` command, but you are using the `--rm` flag which tell the docker deamon to delete the container once it killed, meaning that when the container is stoped auto delete it, therefor you cannot re-start the container.

Your problem is that you are using the docker in a wrong way, you tell the docker container to write the output of the process to the docker container file system and then delete the container, then you try to copy it.

You should use a mounted volume from your host (by using `-v` flag) and write the output there, or you can enter docker with runing the command `/bin/bash` at the end, then you can run the process manually from inside the docker container, wait for it to finished, press `ctrl+p+q` to exit the container without killing it and copy the file using `docker cp` command and then kill the container what ever make you. Note that because `/bin/bash` the container has a process and therefor it will not be killed (as your question was "how to stop from container from dying...").

# Answer
> 0 votes
I don't know about `git-all-secret` specifically, but from what I understand you are trying to capture the output produced by that tool. Since docker maps by default the standard output of a container to the standard output of the client `docker` command, you may achieve the desired result using something like that (untested):

```
sudo docker run --rm -it abhartiya/tools_gitallsecrets -org $org \
     -output /dev/stdout \
     -thogEntropy -token $githubtoken \
 > ./output.txt

```

Many tools allow `-` as a synonym for /dev/stdout, so this might work:

```
sudo docker run --rm -it abhartiya/tools_gitallsecrets -org $org \
     -output - \
     -thogEntropy -token $githubtoken \
 > ./output.txt

```

---
Tags: docker, containers
---


# Question
Title: Jenkins parameters default to env variable?
I am trying to crate parameters field which is default to current build no.

```
parameters {
    string(
        name: 'DEPLOY_BUILD_NUMBER',
        defaultValue: '${BUILD_NUMBER}',
        description: 'Fresh Build and Deploy OR Deploy Previous Build Number'
    )
}

```

But it looks like the assignment of `BUILD_NUMBER` env var to parameter `DEPLOY_BUILD_NUMBER` is not happening.

even following one didn't help

```
steps {
        script {
            if (params.DEPLOY_BUILD_NUMBER == null){
                DEPLOY_BUILD_NUMBER = env.BUILD_NUMBER
            }
        }
}

```

Is there any other way to do this ?

# Answer
> 3 votes
You need to use double quotes instead of single quotes. Single-quoted strings don't perform string interpolation.

For instance:

```
parameters {
    string(
        name: 'DEPLOY_BUILD_NUMBER',
        defaultValue: "${BUILD_NUMBER}",
        description: 'Fresh Build and Deploy OR Deploy Previous Build Number'
    )
}

```

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


# Question
Title: Jenkins: make a credential available to all users
I'd like to allow all of our organization's users to create new pipelines in Jenkins, via Blue Ocean...

This requires a Github access token, meaning I have to either require each user to use their own access token, or share the contents of an access token with all users.

The first option seems inconvenient. The second option is a security risk, and we'd have to change our token any time someone left the organization.

I was hoping to find a way to add a credential to Jenkins and scope it so that all users have access to it, so the above New Pipeline flow would use that cred rather than querying the user to input a token.

I created a token with Global (rather than System) scope, but new users are still asked to input a token when they go to add a pipeline.

Is there a good solution for this? Do most organizations rely on individual developers to use their personal access tokens?

# Answer
I was a little confused by the OP question and follow up, so answering about GitHub access to jenkinsfile-based pipeline jobs: Credentials stored in Jenkins can be available to all users with rights to create jobs. Use a GitHub deployment key for your repo. Yes you need a key for every repo. This does require a user in Github, of course, but there is nothing to stop you from paying for an extra so-called 'machine user.' We, however, just use a real person like me.

This GitHub deploy key allows you to trigger on repo changes, or keep your jenkinsfile in Github. Using jenkinsfiles and keeping them in GitHub, is the best way to do Jenkins, I think.
> 1 votes

---
Tags: jenkins, secret-management
---


# Question
Title: Which libraries generate observability metrics for applications in the cluster to prometheus?
I recently read "Cloud Native DevOps with Kubernetes" by O'reily and it mentions the RED and USE metrics which are a good starting point for gaining better observability into the system, however I'm having a hard time finding any information online about how to actually go about generating those metrics outside of re-inventing the wheel for each service.

Is there a set of libraries to actually generate RED and USE metrics within the application? Or do we have to create a set of utilities for each language and each service independently?

Also, are there known solutions for sending CrashLoopBack or Pending pod metrics to Prometheus or do these also need to be reinvented in house?

# Answer
> 2 votes
For Application specific calls you need to use a Prometheus client and create the metrics yourself. The Prometheus client will allow you to create a `/metrics` endpoint where you can output the current metric values which Prometheus will scrape.

For metrics that are not unique to your application, you can use Prometheus exporters that will run on either the node, container, or runtime environment, or third-party software. These will also create targets which you can tell Prometheus to scrape to gather the metric data.

Once the metric data is collected you'll need to write your own RED and USE queries in graphana to display those metrics.

---
Tags: kubernetes, metrics, prometheus
---


# Question
Title: How to start a VPN connection using Jenkins?
I'm on a Windows Server and I want to have a pipeline project on Jenkins that basically does this:

* SVN update
* Build
* Deploy

As the deploy target machine is on a different network, I want to know how to start a VPN connection before to do the deploy.

Note: My general goal is to automate deployment to a server in a VPN. Currently the VPN is Cisco AnyConnect.

# Answer
> 2 votes
> solutions is: **OpenConnect Plugin**

See here: https://wiki.jenkins.io/display/JENKINS/OpenConnect+Plugin

OR also you can use below method:

On Linux (Debian based)

```
sudo apt-get install openconnect

```

Add the following lines to the bottom of /etc/sudoers (ubuntu configuration)

```
jenkins ALL=NOPASSWD:/usr/sbin/openconnect*
jenkins ALL=NOPASSWD:/bin/kill*

```

Then you will get an option in the Jenkins run task called:

```
Connect to Cisco AnyConnect VPN

```

# Answer
> 0 votes
Using Jenkins to create its own network paths is either clever or crazy. Right now I am leaning toward crazy, and trying to justify this reaction.

VPNs, particularly AnyConnect types, are normally maintained as infrastructure by network engineers and used for multiple uses. But it sounds like you want to deploy from inside your network to inside a customer network. Attaching a physical VPN between you is heavy-handed and likely to run into corporate road-blocks - if I've understood you correctly. Thinking of your problem as IoT causes me to suggest that you have your inside-customer device call up to the Cloud and pull down deployments, which you have staged in the Cloud. If your customer will give you an ingress port ( ours don't very often) you can have a two-way connection where the Cloud server pushes to the IoT device. But pull-only works well.

You can establish a VPN from your IoT device to the Cloud, and in fact, most today would demand that this connection be encrypted in some way.

---
Tags: jenkins, deployment, jenkins-pipeline, vpn
---


# Question
Title: Does Prometheus expose the Horizontal Pod Autoscaler's "Current CPU Utilization" as shown in the Kubernetes dashboard?
In the Kubernetes dashboard, I can see for a HPA the following information:

```
Min Replicas:
3
Max Replicas:
11
Target CPU Utilization:
80%
Status
Current Replicas:
3
Desired Replicas:
3
Current CPU Utilization:
10%
Last Scaled:
5 days

```

However, I can't figure out how the 10% CPU utilization is calculated?

And if this value exposed via Prometheus?

# Answer
> 1 votes
As we can see from kube-state-metrics/docs/horizontalpodautoscaler-metrics.md

We just need to have kube-state-metrics along with HPA to start getting metrics in prometheus.

---
Tags: kubernetes, prometheus
---


# Question
Title: Utilise AWS IoT on non-supported hardware
Before I dig in too far, is there any way I can use any of the AWS IoT core functions on non-supported hardware?

I can use the AWS Node.js libraries that are available (for my hardware), but I don't think this is getting me into the core services.

My alternative is just to build my own ecosystem on existing services like IAM/S3/SNS/EC2.

Thanks for any help!

# Answer
In case anyone else would like to benefit from my experience, the answer is "kind of".

Without a Greengrass kernel, you will not get many of the core features and benefits, but you can use JS/Node SDK to start migrating to AWS IoT.

https://github.com/aws/aws-iot-device-sdk-js

For me, the problem was that my ARM device has an armv61, and Greengrass requires a minimum armv71, which is frustrating for an ecosystem designed for very low power devices.

But, at least I can base some of my back-end on the presumption that we will eventually move to updated hardware.
> 1 votes

---
Tags: amazon-web-services, linux, node.js
---


# Question
Title: How do you monitor status of multiple docker containers?
My home server has about 15 distinct services running, each represented by a Docker container. Depending on how the developers implemented the Dockerfile, some services have health checks, but most do not.

At the moment, I do not have a way to make sure these services remain healthy and running. I do have the `restart: always` setting set, but worst case this just means Docker endlessly restarts a server if it fails to start or crashes on startup for whatever reason. Or maybe a `docker pull` caused an issue during an update. There could be many reasons why these services do not start, or stop running during the day.

What I'd like is to know when they go down. Maybe an email that notifies me, so I can go fix the issue, instead of only finding out about the issue when a family member notifies me or when I try to use that service.

Is there a reasonable way to monitor multiple Docker containers in this way? Do I have to hand-write a bunch of scripts that do `ps` to check for process up time or something? Preferably an out-of-the-box solution would be great. Note I use Docker Compose for everything, and I only have 1 physical machine where I run these services, so I don't need to worry about complex setups.

# Answer
Note: answer based only on docs, I didn't play with docker much.

If you choose scripting you could pick a higher layer than just `ps`, based on either:

> ```
> Usage: events [options] [SERVICE...]
>
> Options:
>     --json      Output events as a stream of json objects
>
> ```
>
> Stream container events for every container in the project.

> **Description**
>
> Get real time events from the server

You'd be looking for the `die` event of the container(from Extended description):

> Use `docker events` to get real-time events from the server. These events differ per Docker object type.
>
> **Object types**
>
> CONTAINERS
>
> * `die`

The event appears to be generated regardless of the restart policy (from Docker Events Explained):

But you're right, there's a ton of monitoring tools out there, I also suspect some already do what you're seeking.

Just aimlessly wandering through those links I got to Implementing Docker event monitoring from scratch:

> What else? **I can create alerts on them**. The next time any of my containers decide to puke and die, I can get an SMS message about their doomed state.
> 3 votes

# Answer
If you don't mind running a few other services at your home, then I'd suggest you try Prometheus with Grafana, dockerd-exporter and AlertManager.

Prometheus will store time series data collected from your dockerd-exporter, Grafana will display that data in a very nice way and AlertManager will allow you to configure alerts based on your needs.

Check out a random screenshot I found on Google that presents the solution:

Also check out swarmprom project.
> 3 votes

# Answer
If most of those are network services, or at least have some administrative TCP/IP port open, then monitoring them by `curl` or `netcat` might not be the worst solution. That's how a full-fledged orchestration solution like OpenShift would do it. So, in somewhat increasing order:

* Check if a TCP/IP port is open (`netcat -z`)
* Check if the port is open and responds with a specific prompt (`netcat | grep HELLO`).
* Check if the port answers with a specific HTML (for example) (`curl ... | grep <p>I'm alive</p>`).

And finally, if nothing else helps:

* Check if a hand-written script returns `true`.
> 1 votes

# Answer
You can use check\_mk for monitoring the health of containers just as you could for any other machine. Read about it here..

Open Source Docker Monitoring Using Check MK

Hope this helps.
> 0 votes

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


# Question
Title: Why `docker diff` does not see some file changes?
I know when you create a container the Docker engine adds a thin writable layer on top of the image layers. And all filesystem changes are recorded in that writable layer.

I know I can use the `docker diff` command to show the changes made in a container's filesystem compared to the base image.

But surprisingly, I cannot *see* where data are saved in the following use case involving the official MongoDB image:

```
sh$ sudo docker run -d --name mongo mongo:3.6.10
sh$ sudo docker exec -i mongo mongo << EOF
> db.test.insert({foo:"bar"})
> EOF
MongoDB shell version v3.6.10
MongoDB server version: 3.6.10
WriteResult({ "nInserted" : 1 })
bye

sh$ sudo docker stop mongo
sh$ sudo docker diff mongo
C /root
A /root/.dbshell
C /tmp

```

`/tmp` is empty. And `/root/.dbshell` is just the history file for the mongo client. But I can't see any trace of the data files modified by the Mongo DB server. However, data were definitely stored:

```
sh$ sudo docker start mongo
sh$ sudo docker exec -i mongo mongo << EOF
> db.test.find()
> EOF
MongoDB shell version v3.6.10
MongoDB server version: 3.6.10
{ "_id" : ObjectId("5c750d4cef8f9635fe459f06"), "foo" : "bar" }
bye

```

And I can find the data when I manually dump the files:

```
sh$ sudo docker exec mongo bash -c 'tar c /data/db/collection*' | hexdump -C | grep foo
tar: Removing leading `/' from member names
0000e840  02 66 6f 6f 00 04 00 00  00 62 61 72 00 00 00 00  |.foo.....bar....|

```

**Why can't I find the data files modified by the MongoDB server using `docker diff`? Did I make some wrong assumption somewhere? Or did I misunderstood something regarding the way `docker diff` works?**

# Answer
I don't know how I missed that, but the mongo image by default stores data in a Docker managed volume, and not in the container writable layer as I assumed it initially.
> 1 votes

---
Tags: docker, audit
---


title: Looping through found files in Ansible

text:
# Question
Title: Looping through found files in Ansible
I am trying to set the sendmail\_path to use Mailhog in all php.ini files on a server with multiple versions of PHP installed for PHP FPM.

Why is the following snippet is not working?

```
- hosts: localhost
  tasks:
    - name: Find ini files
      find:
        paths: /home/myuser/projects/infra/php
        file_type: file
        recurse: Yes
        patterns: "*php.ini"
      register: files_matched

    - name: Debug files_matched
      debug:
        var: files_matched.files

    - name: Debug files_matched loop
      debug:
        var: item.path
      loop: "{{ files_matched.files|flatten(levels=1) }}"
      loop_control:
        label: "{{ item.path }}"

    - name: Ensure "sendmail_path=/opt/mailhog/mhsendmail is in section "[mail function]"
      ini_file:
        path: item.path
        section: "mail function"
        option: sendmail_path
        value: /opt/mailhog/mhsendmail
        mode: 0644
        backup: no
      loop: "{{ files_matched.files|flatten(levels=1) }}"
      loop_control:
        label: "{{ item.path }}"

```

The error I am getting is essentially **No such file or directory: ''** on the `item.path` variable.

```
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: OSError: [Errno 2] No such file or directory: ''
failed: [localhost] (item=/home/myuser/projects/infra/php/7.0/fpm/php.ini) => {"changed": false, "item": {"atime": 1551116700.7761922, "ctime": 1551115509.596934, "dev": 66309, "gid": 1000, "gr_name": "myuser", "inode": 5640238, "isblk": false, "ischr": false, "isdir": false, "isfifo": false, "isgid": false, "islnk": false, "isreg": true, "issock": false, "isuid": false, "mode": "0644", "mtime": 1544171307.0, "nlink": 1, "path": "/home/myuser/projects/infra/php/7.0/fpm/php.ini", "pw_name": "myuser", "rgrp": true, "roth": true, "rusr": true, "size": 70999, "uid": 1000, "wgrp": false, "woth": false, "wusr": true, "xgrp": false, "xoth": false, "xusr": false}, "module_stderr": "Traceback (most recent call last):\n  File \"/home/myuser/.ansible/tmp/ansible-tmp-1551192384.86-125024514722793/AnsiballZ_ini_file.py\", line 113, in <module>\n    _ansiballz_main()\n  File \"/home/myuser/.ansible/tmp/ansible-tmp-1551192384.86-125024514722793/AnsiballZ_ini_file.py\", line 105, in _ansiballz_main\n    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\n  File \"/home/myuser/.ansible/tmp/ansible-tmp-1551192384.86-125024514722793/AnsiballZ_ini_file.py\", line 48, in invoke_module\n    imp.load_module('__main__', mod, module, MOD_DESC)\n  File \"/tmp/ansible_ini_file_payload_yVPEa4/__main__.py\", line 342, in <module>\n  File \"/tmp/ansible_ini_file_payload_yVPEa4/__main__.py\", line 322, in main\n  File \"/tmp/ansible_ini_file_payload_yVPEa4/__main__.py\", line 151, in do_ini\n  File \"/usr/lib/python2.7/os.py\", line 157, in makedirs\n    mkdir(name, mode)\nOSError: [Errno 2] No such file or directory: ''\n", "module_stdout": "", "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 1}

```

As you can see from the error and debug output the file path should not be empty.

# Answer
OK. The answer was simple. I needed to template the item.path. I guess this is a beginner mistake.

```
- hosts: localhost
  tasks:
    - name: Find ini files
      find:
        paths: /home/myuser/projects/infra/php
        file_type: file
        recurse: Yes
        patterns: "*php.ini"
      register: files_matched

    - name: Debug files_matched
      debug:
        var: files_matched.files

    - name: Debug files_matched loop
      debug:
        var: item.path
      loop: "{{ files_matched.files|flatten(levels=1) }}"
      loop_control:
        label: "{{ item.path }}"

    - name: Ensure "sendmail_path=/opt/mailhog/mhsendmail is in section "[mail function]"
      ini_file:
        path: "{{ item.path }}"
        section: "mail function"
        option: sendmail_path
        value: /opt/mailhog/mhsendmail
        mode: 0644
        backup: no
      loop: "{{ files_matched.files|flatten(levels=1) }}"
      loop_control:
        label: "{{ item.path }}"

```
> 5 votes

---
Tags: ansible
---


# Question
Title: Microsoft DevOps: build triggering vs release
I have this setup:

1. Build 1 builds and trigger Release 1 when finished
2. Build 2 is triggered by Build 1 and release Release 2

If I have one parallel job, can I be sure that:

* Release 1 is always run before the Build 2 is triggered?

I have tested this, and it does the above, but I can't find any documentation on the flow anywhere.

I need to release Release 1 before build 2 starts.

# Answer
Do not trigger Build 2 automatically from Build 1. Instead add a last step to Release 1 to queue Build 2. There are a few ways to do it, e.g. https://stackoverflow.com/questions/52821204/how-to-queue-build-pipeline-as-task-from-release-pipeline
> 1 votes

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


# Question
Title: Maintaining Jenkins configuration with docker
I'm trying to configure CI with Jenkins for my private project. Problem:

* whenever I start building a pipeline project, it gives me ,,Docker is not found'' error
* whenever I try to work around this by installing npm plugin and running bash script `npm install` as a build step, I get node/npm not found

Solutions I've found and tried:

According to official Jenkins docker image docs, all one is supposed to do is to mount docker.socket in dockerfile/docker-compose file and it should ,,just'' work (it doesn't) - example:

```
volumes:
     - /var/run/docker.sock:/var/run/docker.sock

```

The only solution that was close to working as intended, was to install docker directly on Jenkins container and then setting user for jenkins. It works, but only until docker image is running. When I kill it and run it again, docker isn't installed on container and so every pipeline fails again. I can't have that, I cannot have a downtime caused by say remote server being down. I'd have to manually install docker on that Jenkins container every time something was down.

Any ideas?

# Answer
> 1 votes
1. There are two ways to run Jenkins builds.
    1. The build node executes the build. In that case, all tools the build needs have to be installed on that node/slave.
    2. The build is run inside a Docker container (with a build node as host). In that case, the Docker image for the build needs to contain all the tools the build needs, but the Jenkins node doesn't have to.
2. "Kill and run again" as in `docker stop $name; docker rm $name; docker run ...`? Sure, that deletes all data local to that container.

* If you want to stop and restart the same container, use `docker stop` and `docker start` instead.
    * If you want to carry data over from one container to another, use volumes.
3. If you want to go with 1.1 and you need all your Jenkins nodes to come equipped with a certain set of tools (such as Docker, npm, ...), create your own Docker image for them.

---
Tags: docker, jenkins, continuous-integration
---


title: Docker build not picking up built jar?

text:
# Question
Title: Docker build not picking up built jar?
I am new to the DevOps world but I am trying to build a pipeline using Jenkins and Docker.

I have Jenkins building the docker image by:

```
docker build -f Dockerfile --build-arg jenkins_jar_file=${JENKINS_JAR_FILE} -t ${DOCKER_IMAGE} .

```

Where JENKINS\_JAR\_FILE is a variable that points to the jar file produced by Jenkins

This is my Dockerfile:

```
FROM ~~container_on_private_registry~~
USER root
WORKDIR /root
ARG jenkins_jar_file
RUN mkdir -p /root/app/app.jar
COPY ${jenkins_jar_file} /root/app/app.jar
ENTRYPOINT ["java", "-jar", "/root/app/app.jar"]

```

However, I feel like the image is not being built with the right JAR? I run docker images and see my image - but it says "Created 4 Days ago" I see the same thing when I run docker images histroy for the entrypoint step.

When I actually try to run the image against a container, it for some odd reason tries to run against a jar which doesn't exist in the image. Instead it returns the following error: /root/app-1.0-20180729.204127-14

Any help appreaciated :)

# Answer
> 1 votes
It seems to me that your Dockerfile should be looking like this:

```
FROM ~~container_on_private_registry~~
USER root
WORKDIR /root
ARG jenkins_jar_file=jenkins.jar
ENV jenkins_jar_file ${jenkins_jar_file}
RUN mkdir -p /root/app
COPY ${jenkins_jar_file} /root/app/app.jar
ENTRYPOINT ["java", "-jar", "/root/app/app.jar"]

```

**Explanation:**

We tell the Dockerfile to let Docker know, that it expects a variable named jenkins\_jar\_file to be passed to it during the build. Subsequent lines can reference that variable with a dollar notation.

Also when you build the image, use --no-cache so it will re-build all the layers of the image.

# Answer
> 0 votes
You can add one more step before running build and list the jars to ensure that this is the right jars then copy them to the place where is your Dockerfile and run the build

---
Tags: docker, jenkins, dockerfile, java
---


# Question
Title: How to make Load balancer to wait for custom program to finish running?
I have a problem I am trying to solve. When the auto scaling creates a new EC2 instance, the load balancer gets a positive health check result fairly quickly. However, the problem is that we have a custom application that runs when an instance starts and we do not want the instance attached to the load balancer until it has completed. So I need to find a way to make the load balancer wait until our custom application is finished running. What is the best way to accomplish this?

# Answer
> 2 votes
Use the health check capabilities to ensure that your instance is not in service before your custom program is ready.

If you have a classic ELB, you can point to an specific enpoint, for example, /health\_check.php that performs the necessary checks in your application to ensure that your custom program is ready. Then, when a new instance is attached to the load balancer, it will perform the health check action that you have configured an expects a right behaviour of it. If not, the health check fails and will continue to perform new health checks in the configured intervals until instance become in service.

On best practice for web servers behind a load balancer, for example, is to add an specific endpoint that checks that all the necessary pieces for your application is running and in service, that is database, storage, caching processes or whatever you new or consider critical for your system.

The official AWS documentation is very useful for this.

Hope this helps

---
Tags: amazon-ec2
---


# Question
Title: What is the difference between Container Engine Software and Container Management Software
What is the difference between Container Engine Software and Container Management Software ?. Docker/kubernetes are managements softwares whereas Apache Mesos/Rocket are Container Engine softwares. Please explain.

# Answer
I see a lot of confusion in the question. Docker is a containerization software whereas Kubernetes and Mesos are container management softwares. While Kubernetes is a software for cluster management of containers(not necessarily for docker) and microservices, Apache Mesos is an orchestration technology for cluster management softwares like Kubernetes.

All these three types of technology are aligned to work together.

In layman terms, you (can) run Docker within Kubernetes which you (can) run within Mesos.

Please have a read here for more explaination.
> 2 votes

---
Tags: docker
---


# Question
Title: How to handle item not in list in ansible variable?
This question may look strange as something like this is not implemented in real life. I have tried to make it very general.

Here is my ansible-playbook:

**tasks/main.yml**

```
- name: "Setting place name of {{ country }}"
  set_fact:
     place: "get_place_name"

- name: "Setting places name of {{ country }}"
  set_fact:
     places: "get_places_name"

- name: Details of "{{ country }}"
  debug:
    msg: "{{ item }}"
  when:
    -  place in "{{ item.Other_Places }}" or places in "{{ item.Other_Places }}"
  with_items: "{{ Places }}"

```

**vars/main.yml**

```
---
Places:
- Country: "United States of America"
  Capital: "{{ capital }}"
  Other_Places: ['place1', 'place2']

- Country: "China"
  Capital: "{{ capital }}"
  Other_Places: ['places1', 'places2', 'places3', 'places4']

```

Here if "place" variable is defined as "place1" then it will run and output will be something as below:

```
"msg": {
        "Country": "United States of America",
        "Capital": "place1",
        "Other_Places": "['place1', 'place2']"
    }

```

The problem is I am confused on how to handle something that is not listed in "Other\_Places"? Suppose I input "place10" as variable name "Capital" then it is not defined then it should simply output "Sorry, no matching place found."

If we do something like below :

```
- name: Exceptional case
  debug:
    msg: "{{ capital }} not in {{ item.Capital }} "
  when:
    -  place not in "{{ item.Other_Places }}" and places not in "{{ item.Other_Places }}"
  with_items: "{{ Places }}"

```

This will output all at once because "place" is not defined in "capital".

# Answer
use the condition

```
- when: variable is defined
  run_module_when_defined:

```

or

```
- name:
  block:
    - task1
    - task2
  when: variable is defined

```
> 3 votes

---
Tags: ansible
---


# Question
Title: Which S3 buckets is Lambda allowed to read code from?
There doesn't seem to be any way to define a policy about which S3 buckets Lambda is allowed to run code from.

With most services in AWS, the usual practice is to define an IAM role that can be assumed by the AWS service so that it can perform work on user-created resources in the account. For instance, Kinesis Firehose isn't allowed to write into one of your S3 buckets until it's explicitly granted permission with an IAM role.

Even with Lambda we have the concept of an execution role, that is the IAM role that can be used by custom code in our Lambda. But that still takes place *after* the code has been loaded.

# Answer
> 0 votes
This represents a misunderstanding of when Lambda code is loaded.

AWS Lambda does **not** download a copy of the code from S3 every time a function is executed. Instead, Lambda has its own internal storage that is updated when invoking `CreateFunction` or `UpdateFunctionCode` either through the API or the Console.

*Update with further clarification from jdog:*

> Lambda is never given access to S3 buckets -- the user or role that runs CreateFunction is.

---
Tags: amazon-web-services, aws-lambda, aws-iam
---


# Question
Title: Where is it said I can safely the same local volume to multiple docker containers?
According to that StackOverflow answer:

> Yes you can add same location as a volume to many docker containers.

But I read the Docker Volume documention and I can't find where it is said a *local* volume can safely be shared between several containers on the same host. Could someone point me to an official statement regarding that?

# Answer
> 1 votes
By a "local volume" I assume you mean a block device directly attached to the host, such as a "normal" internal disk.

The standard way to run multiple Docker, containers now is Kubernetes, since the demise of Docker Swarm. My reference here is the Kubernetes documentation for Persistent Volumes specifically the table on Access Modes, and the column for *ReadWriteMany*. A local volume would be a *HostPath* which is *not* supported for this use case. However if you were using iSCSI it would support *ReadOnlyMany*, and if you used NFS you could get *ReadWriteMany*.

---
Tags: docker, volume
---


# Question
Title: Kubernetes on k3s can't resolve domains from custom dns server (fritz.box with dnsmasq)
I have a dns server running at 192.168.0.19 for custom domains like .fritz.box. Having a single node cluster on k3s, Rancher was installed using a subdomain server2.fritz.box using this command:

```
    helm install rancher-latest/rancher \
      --name rancher \
      --namespace cattle-system \
      --set hostname=server2.fritz.box

```

Rancher itself shows that some services are not avaliable and the logs from cattle say server2.fritz.box is not avaliable. Since Kubernetes has its own dns system, I looked at the documentation and it seems that I need to set my .19 dns server so that Kubernetes knows how to resolve .fritz.box domains. Some questions also have similar problems like https://stackoverflow.com/questions/41448095/kube-dns-does-not-resolve-external-hosts-on-kubeadm-bare-metal-cluster

So I created the following yaml:

```
# https://github.com/kubernetes/kops/issues/4986
apiVersion: v1
kind: ConfigMap
metadata:
  name: kube-dns
  namespace: kube-system
data:
  stubDomains: |
    {"fritz.box": ["192.168.0.19"]}
  upstreamNameservers: |
    ["192.168.0.19"]

```

Loaded with `kubectl apply -f dns.yml`. Now created a busybox test pod:

```
~$ kubectl exec -it busybox -- ping server2.fritz.box
ping: bad address 'server2.fritz.box'

```

Why is this not working? And what must be done to resolve a custom dns server in Kubernetes?

# Answer
> 5 votes
ibuildthecloud9 gave me the right hint. Since the github issue doesn't describe how to midify the dns, I figured it out and want to document it here in case someone need to change it, too. It's stored in the configmap `coredns` as `Corefile`:

```
proxy . 1.1.1.1

```

You need to replace this by your dns server (192.168.0.19 in my case). It could be done manually using `kubectl edit cm -n kube-system coredns`. In case you also want to automate this process:

```
kubectl get cm -n kube-system coredns -o yaml | sed "s/proxy . 1.1.1.1/proxy . 192.168.0.19/g" > coredns-fixed.yml

```

Now you'll have the fixed yaml file, which got loaded by

```
kubectl apply -f coredns-fixed.yml

```

## Test it

Create `busybox.yml`

```
apiVersion: v1
kind: Pod
metadata:
    name: busybox
spec:
    containers:
    # for arm
    #- image: hypriot/armhf-busybox
    - image: busybox
      command:
          - sleep
          - "3600"
      imagePullPolicy: IfNotPresent
      name: busybox
    restartPolicy: Always

```

Create the pod: `kubectl create -f busybox.yml` And try to ping a host resolved by your dns:

```
~$ kubectl exec -it busybox -- ping -c1 server2.fritz.box
PING server2.fritz.box (192.168.0.37): 56 data bytes
64 bytes from 192.168.0.37: seq=0 ttl=61 time=0.386 ms

```

**Before** applying our dns (so 1.1.1.1 was used, which belongs to Cloudflare) this throws the following resolving error:

```
*~$ kubectl exec -it busybox -- ping -c1 server2.fritz.box
ping: bad address 'server2.fritz.box'*

```

# Answer
> 4 votes
I believe this is an current bug in k3s that upstream DNS is hardcoded to 1.1.1.1. this should be resolved shortly https://github.com/rancher/k3s/issues/53

---
Tags: kubernetes, configuration-management, helm, dns, rancher
---


title: Ingress or LoadBalancer on AKS

text:
# Question
Title: Ingress or LoadBalancer on AKS
I'm wondering whether to use an Ingress or LoadBalancer to expose services on Azure AKS.

I have successfully used both, but I cannot really choose. On one side, an Ingress allows us to have a single public IP address, but on the other end it factorizes all the routes inside one Ingress so deployment means impacting all the routes.

Would you recommend:

* a common Ingress for all applications
* an Ingress for each application;
* a LoadBalancer for each service ?

# Answer
> 2 votes
just create an ingress resource along side each application, that way you can modify individual ingress resources without impacting other applications. Load balancers do not allow you to do anything meaningful with your traffic.

With ingress you can use cert-manager, external-dns, ssl offloading, etc.

# Answer
> 1 votes
I generally use an Ingress for each application. This allows for any updates to it to be specified as a separate deployable unit. If there is a need for separate public IPs, you can have multiple ingress controllers for different namespaces/environments.

---
Tags: kubernetes, azure, azure-kubernetes-service
---


# Question
Title: What are the advantages of using Jenkins over Hudson?
Jenkins is a fork of Hudson.

What are the benefits/advantages of using Jenkins over Hudson for a small private business?

# Answer
Number of commits.

Jenkins is a fork of Hudson (as commented here) but has a more active development, Hudson's last commit is quite old. And look at Hudson's open bugs
> 15 votes

# Answer
In short: the community. I developed a Jenkins plugin recently, and supporting Hudson did not even cross my mind (Jenkins has waaay more plugins).
> 6 votes

# Answer
**Jenkins is better Because**

* most users moving on to Jenkins, as well as other adoption metrics indicating clear shift in the userbase.
* the Hudson team has moved to develop Jenkins. So you can trust our expertise and the the passion to keep pushing the software forward.
* a large number of plugin authors have chosen to support their plugins on Jenkins. So you can expect bug fixes and new improvements to them from Jenkins.
* we'll make incremental iterative improvements to the code.
* the community supports us.
* well maintained documents. (Credits: Martin Lee)

**Few more noticeable points are (from StackOverflow)**

* Hudson/Jenkins is the product of a single genius intellect - Kohsuke Kawaguchi. Because of that, it's consistent, coherent, and rock solid. (By Jonik)
* Oracle now owns hudson and Jenkins is open-source. Both are MIT Licensed. Describing one as open-source and the other as other-than-open-source is misleading. They're free software (By pb2q)
* Hudson/Jenkins is all about the plugins. Plugin developers have moved to Jenkins and so should we, the users. (By Tim Fulmer)
> 3 votes

---
Tags: jenkins, software-recommendation, hudson
---


# Question
Title: Is it necessary to specify resource in S3 Bucket Policies?
Is it necessary to specify a **resource** attribute within the statements that make up an S3 bucket policy? The Access Policy Language Overview seems to suggest that the resource attribute is always included, though it doesn't come straight out and say it's *required*. Consider this example policy shown on the language overview page.

```
{
  "Version": "2012-10-17",
  "Id": "ExamplePolicy01",
  "Statement": [
    {
      "Sid": "ExampleStatement01",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::Account-ID:user/Dave"
      },
      "Action": [
        "s3:GetObject",
        "s3:GetBucketLocation",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::examplebucket/*",
        "arn:aws:s3:::examplebucket"
      ]
    }
  ]
}

```

A bucket policy is assigned to an S3 bucket, so it seems like the policy would always be evaluated in the context of the bucket that it's assigned to. Based on that, it seems like it should be possible to omit the **resource** attribute.

If the resource attribute really is required, is it possible to use a wildcard arn like this? Would that carry any risks, or would it simply allow access to the bucket exactly as if the bucket was named in the policy?

```
      "Resource": [
        "arn:aws:s3:::*",
        "arn:aws:s3:::*/*"
      ]

```

*(For greater clarity, I am NOT talking about IAM policies in this question.)*

# Answer
Yes, **Resource** is a required element on S3 bucket policies. If the resource is omitted, the API will respond with an error resembling this one below.

```
status code: 400
Error putting S3 policy: MalformedPolicy: Statement is missing required element

```

The reasoning is that each statement could apply to the bucket itself, the contents of the bucket, or some subset of the bucket contents, and it's up to the user to clarify. In theory AWS could provide a default that includes both the bucket and all of its contents, but that design probably wasn't chosen because it makes it too easy to accidentally make the bucket policies broader than expected.

Additionally, it is **not permissible** to use a wildcard in the resource element of an S3 bucket policy. Attempts to do so will yield an error such as this:

```
Error putting S3 policy: MalformedPolicy: Policy has invalid resource

```
> 5 votes

---
Tags: amazon-web-services, amazon-s3
---


title: Secure Jenkins X on kubernetes

text:
# Question
Title: Secure Jenkins X on kubernetes
I have installed Jenkins X on kubernetes. I want to change the default installation and secure the Jenkins url, so that it will be not accessible to the public.

Can I change it to some port, or some way to have a firewall for only few IPs allow to access the Jenkins URL.

# Answer
> 1 votes
In my experience, the easiest way to do this is to put Jenkins behind an SSL-terminating proxy, such as Apache or Nginx. You can also configure SSL within Jenkins itself, but I've found that using a proxy is usually a lot easier to set up and manage with regards to SSL.

---
Tags: jenkins, kubernetes, jenkins-x
---


# Question
Title: How to make Jenkinsfile credential visible to many stages
In Jenkinsfile, I want to make an `ssh key` visible to all stages in the pipeline.

From the official document, I learned that:

1. `environment` directive is used to defy environment variables for used within Jenkinsfile
2. The scope of the variables defined depends on the placement of the `environment` directive
3. One can set the **some types of credentials** inside`environment` directive with the help of the `credentials` helper
4. The types of credentials supported by the helper are:
    * Secret text
    * Usernames and passwords
    * Secret files

For other types of credentials, the document suggests using the `snippet generator`, which generates a step.

Example of an ssh key step

```
withCredentials([sshUserPrivateKey(credentialsId: 'jenkins_aws_to_bitbucket', keyFileVariable: 'BITBUCKET_PRV_KEY')]) {
    // some block
}

```

This is meant to be used in a *stage* like:

```
pipeline {
    agent {
        // define agent details
    }
    stages {
        stage('Example stage 1') {
            steps {
                withCredentials(bindings: [sshUserPrivateKey(credentialsId: 'jenkins-ssh-key-for-abc', \
                                                             keyFileVariable: 'SSH_KEY_FOR_ABC')]) {
                  //
                }
                withCredentials(bindings: [certificate(credentialsId: 'jenkins-certificate-for-xyz', \
                                                       keystoreVariable: 'CERTIFICATE_FOR_XYZ', \
                                                       passwordVariable: 'XYZ-CERTIFICATE-PASSWORD')]) {
                  //
                }
            }
        }
        stage('Example stage 2') {
            steps {
                //
            }
        }
    }
}

```

*Snippet source*

**Question**

1. If the steps are within a *stage*, are these credentials visible within other stages?
2. If not, how to make these credentials *global* ~ visible within all stages

# Answer
> 8 votes
The credentials will only be visible within the block passed to `withCredentials`, not outside of that. So, no, your credentials will not be visible to other stages. To make your credentials visible to your entire Pipeline:

* If you are using Declarative Pipelines, you can put your credentials in an `environment{}` block at the top of your Pipeline, as documented in the official Jenkins handbook:

```
pipeline {
    agent {
        // Your agent here
    }
    environment {
        MY_ENVIRONMENT_VARIABLE = credentials('my-credentials-id')
    }
    stages {
        // Your stages here
    }
}

```
* If you use Scripted Pipelines, you can wrap your entire job in `withCredentials`. This is not possible with Declarative.

# Answer
> 4 votes
I set credential globally in declarative pipeline like this and then my Jenkins could talk with Google Dataflow in all stages. For example, I used a secret file (google service account).

```

pipeline {
    agent any
    environment {
        //Secret File ID was defined in Jenkins -> Credentials -> System -> Global credentials
        GOOGLE_APPLICATION_CREDENTIALS = credentials('mySecretFileId')

        GCP_PROJECT_NAME = 'myProject'
    }
   stages {
             stage('step 1') {
              steps {
                sh "gcloud auth activate-service-account --key-file ${env.GOOGLE_APPLICATION_CREDENTIALS}"
                sh "gcloud config set project ${env.GCP_PROJECT_NAME}"

                // access google dataflow
                sh "gcloud dataflow jobs list --status=active"
                // ....
              }
             }
             stage('stage 2') {
               steps {
                  // access google dataflow
                  sh "gcloud dataflow jobs list --status=active"
               }
             }
             //...
   }
}

```

---
Tags: jenkins, jenkinsfile
---


# Question
Title: Are microservices "cloud-ish medium-lived services"?
According to https://events.static.linuxfound.org/sites/events/files/slides/cc15\_mcguire.pdf p21-23, Kevin McGuire of New Relics classifies the containers in three categories:

* VM-like with a lifetime \> 1000h
* "Cloud-ish" with a lifetime between 24 and 1000 hours
* Lightweight compute engine with a lifetime \< 24h (and even \<1h for 46% of them)

I have hard-time to clearly define what are the "cloud-ish" containers:

1. Are those typically "microservices" or is this something different?
2. Would you put applications that scale on demand as part of those "cloud-ish" services, or would they fall into the "lightweight compute engine" category instead?

# Answer
> Are those typically "microservices" or is this something different?

"Cloud-ish" services could include microservices. I would include services that are replicated and/or load-balanced, such that you can sustain downtime on a single machine, VM, or running binary without service disruption.

Their differentiation of VM-like services looks like services which have a lot of local state (in memory or on disk) where frequent restarting would incur lots of downtime (from either the time it takes to boot/populate a new VM or because the service is singly-homed.)

> Would you put applications that scale on demand as part of those "cloud-ish" services, or would they fall into the "lightweight compute engine" category instead?

They could be in either category. Scaling on demand is a commonly-used "feature" of Cloud computing. Think of "Lightweight compute engine" tasks as things like batch jobs, manually run jobs, one-offs etc.
> 1 votes

# Answer
Calling containers cloud-ish is simply child-ish. :)

Well, I think the author is trying to classify the containers on the basis of their life-times. I don't see that they have considered any form of Agile working methodology here. In SCRUM, for instance, you would not have the containers running more than a few days. A very aggressively agile team would probably push new containers several times a day, thereby destroying older containers. Also, I think the dataset is small for a concrete classification in this case.

And here's to answering the question for the sake of it. :)

> Are those typically "microservices" or is this something different?

Ans: Assuming that the data is correct, I would say the short-lived containers are mostly created for managing load. This could be microservices or asynchronous processing(where a container is killed after job is completed).

> Would you put applications that scale on demand as part of those "cloud-ish" services, or would they fall into the "lightweight compute engine" category instead?

Ans: They can be either the Lightweight or the 'cloud-ish' servers depending upon what the load is computed to be.
> 0 votes

---
Tags: terminology, term-disambiguation
---


# Question
Title: How do I deploy an applications to Kubernetes with Minikube?
I would like to do something like this, but all Kubernetes quickstart demos are just for deploying a simple applications and not multiple.

How would I create a yaml file that can deploy multiple applications like this with Minikube?

# Answer
Welcome to the wonderful world of container orchestrators. It is considered bad practice to install many apps into a single container. The new way of working is not to install an application server that runs many WAR files. The new way of deploying is to have each app be a self-contained container where your build tool (eg maven) packaged the servlet container and your app together into a single file. Then each container can be deployed to Kubernetes and independently scaled up and restarted. They can also have memory leaks and crash without effecting each other.

One good example of that is springboot where in your pom.xml you can tell it to build an executable JAR. This will be large as it will include Tomcat into it. When you run the executable file it will launch java and Tomcat and bind to a port and run your app. You don't have to use springboot you can simply add the Tomcat or Jetty plugin to your maven project and have the container just launch "mvn jetty:run" or "mvn tomcat7:run".

I recommend you try minishift which is like minikube but the openshift distro of kubernetes that has more devops features. If you want to deploy Java Servlet apps you just use its built in catalog, select "Open JDK" supply it with your git repo, and it will checkout your code, build the app with maven, create a container image, and deploy the it, with a route and URL you can access it. Yet you can create things from scratch the catalog is just creating all the necessary YAML. Here is the sample code that you would use as your maven project that can be built and run by the "Open JDK" catalog. The pom.xml shows that when the code is built with `mvn -P openshift package` it puts the war file into a deployments folder and jboss will run it when the container is started. If you don't like jboss then you can add a `.s2i/bin/run` script that starts your compiled application another way (e.g. "mvn jetty:run" or "mvn tomcat 7:run")

Helm is a package manager for Kubernetes it works with openshift extensions also. Helm tracks what your have installed and lets you rollback. The official chart repos have ready made charts to install databases and redis etc. I made a generic chart that runs any container on openshift kubernetes and we use it to install all our apps whether mode.js or php or whatever. It uses the same YAML as the built in templates use.

When you want to install many charts then you can use Helmfile. Your Helmfile has all the yaml to install all your helm charts. The best feature is that it only modifies what changed. If you modify one setting in a Helmfile that configures many apps it will only update the one app. And let you see the prior versions of the k8s yaml of the apps store in k8s and lets you easily rollback to the last working state.

I am making open source the stuff we run a business with as “OCD” where you change the config in git and a webook will run Helmfile to update your Kubernetes env. Here is the minishift demo how-to.
> 3 votes

# Answer
As I understand you need to run and Application which is loading it Servlet container and using reverse proxy to serve the static content and you also want that your sample.war and other configuration remains there regardless of the container life cycle.

Here is an Example project which exactly what your are looking for. Please see this project on Github

Please let me know if you stuck somewhere around. I am glad to assist you.
> 0 votes

---
Tags: kubernetes, minikube
---


title: Passing secrets to a Docker container

text:
# Question
Title: Passing secrets to a Docker container
I have a base docker image which is used to run image analysis software. For each container created from the image, there are a set of configuration settings, some of which are secrets (encryption keys, customer information, etc.), that are used by the software to analyze and distribute the processed images. How can I safely pass these secrets to a container?

# Answer
> 43 votes
You have 3 methods to get secrets to an app inside a docker container. The first 2 involve docker configuration. The last one is to have your apps directly fetch secrets from a secret store.

# 1 - Environment variables

According to "The 12 Factor App" guide, secrets are merely config, and they should always be set in the environment. You could set your secrets as environment variables during the docker run, and your app accesses them from there.

# 2 - Mounted volumes

You could have your secrets all within a particular configuration/secrets file, then mount that to your instance as a mounted volume.

# 3 - Fetch from secret store

As @030 mentioned, you can use Hashicorp Vault (or "Amazon Secrets Manager", or any service like that).
Your app, or a sidecar app can fetch the secrets it needs directly, without having to deal with any configuration on the Docker container. This method would allow you to use Dynamically created secrets (a very appealing feature of such systems) and without having to worry about the secrets being view-able from the file system or from inspecting the env variables of the docker container.

## Personal Opinion

I believe env variables is the way to go. It's easier to manage, and you can still pull from a secret store like Hashicorp Vault, if you have you CI build system pull the secrets during the build and set them when you deploy. You get the best of both worlds, and the added benefit of your developers not needing to write application code to fetch secrets. ~~Devs should be focused on their code functionality, and not dealing with admin tasks like fetching passwords.~~

Your application's code should be focused on it's own app functionality itself, and not dealing with backend tasks like fetching passwords. Just like the 12 Factor App states.

*Edit:* changed last sentence to remove implication of Developer vs SysAdmin silo-ing. The tasks themselves should be separate from a code perspective, but DevOps is about the same persons keeping both in mind and not be limited.

## Personal Opinion (Update)

Per @Dirk's excellent comment (Passing secrets to a Docker container), there is a *very* strong argument to prioritize a secret store over ENV vars, due to not wanting to leak them.

# Answer
> 3 votes
There is another option only using pipe:

```
docker run -d -i --name $n alpine sh -c 'read A; echo "[$A]"; exec some-server'
docker exec -i $n sh -c 'cat > /proc/1/fd/0' <<< _a_secret_

```

First, create the docker daemon with `-i`, the command `read A` will hang waiting for the input from `/proc/1/fd/0`; Then run the second docker command, reading the secret from stdin and redirect to the last hanging process.

---
Tags: docker, secret-management
---


title: Why is build size such a concern?

text:
# Question
Title: Why is build size such a concern?
I often hear (from people, but also from informative CLIs) that the "build/slug size is large". This is particularly so when the build is 0.5 - 2 GB in size

Why (or under what circumstances) is build size such a concern?

Note: the reason I ask is because I see resources like storage and compute as being relatively cheap compared to in the past, so, if anything, I would expect build size to be less of an issue now than in the past

# Answer
When I raise build size issue as a concern, it usually doesn't come from "it is so big, it will be expensive to store it".

The main problems with large builds are the following -

* increased shipping time. moving big bits from place to place frequently is time consuming.
* frequent changes to big artifacts plus a large enoug retention period make storing such artifacts become costly, less so with layered artifacts like docker images.
* creating such big artifacts usually is time consuming, more so than creating much smaller artifacts. automating the process to create smaller artifacts might take time, but the automation that is repeatable should be as short as possible to allow for fast feedback.
* recovering from failure (depending on configuration) might take more time with larger artifacts, especially when an older artifact needs to be reapplied instead of a faulty new-er one.

I subscribe to the four devops metrics:

* Lead time for changes - shorten it
* Deployment frequency - increase the frequency
* Time to restore service - shorten it
* Change failure rate - reduce it to never

Large artifacts usually create a problem in each of these metrics, and none of these metrics are really concerned with the cost of storage really - because that is cheap, time is expensive.
> 11 votes

# Answer
Complementing Evgeny's answer with a few more examples.

What you mean by build size may matter a bit:

* if it is the size of the artifact(s) being built (each one individually or their combined size) - that could matter in artifact storing or use/deployment operations if those operations have size limits and they are exceeded. For example Google App Engine apps has such deployment limits, if reached deployments would fail, see Error when deploying to Google App Engine.
* if it is the size of the workspace in which you perform the build it may matter from the workspace management perspective. Even 2G may be significant - for example if you're building in a RAM filesystem on a machine with not a lot of RAM. But some builds could a lot bigger - I had to deal with 500G+ workspaces (when most of my server disks were below 1T).

If the build is part of your CI/CD pipeline then the larger the build size the longer will the pipeline execution time be (performing the actual build and, if applicable, archiving, deploying for testing, analyzing in case of failure, cleaning up, etc.) - the slower/riskier/costlier your overall development may be.

If you hit a hard limit you'll have to get creative to work around it (not always simple/possible). If it's just a performance/cost hit you also have the option of accepting and living with it and/or addressing it partially/gradually.

It may be worthy to distinguish between:

* bloated builds - when size is unnecessarily increased - fixing the problem is usually possible by dropping unnecessary parts
* the cases in which the content of the build itself is what's really needed - the size doesn't matter as much - it is needed, the only way to address may be by sacrificing some functionality
> 6 votes

# Answer
I'll add a very concrete issue that we actually run into. It's a sideeffect of bad architecture that we're suffering currently:

Since our build is large and we need to load a lot of dependencies simply putting it all together takes a very long time. We should have long since divided the build up into numerous small builds as an approach to a microservice architecture instead of one large monolith.

Running all tests for the monolith takes around 45 minutes and blocks our CI environment for the time being.

Since it's so load intensive and takes such a long time it's currently impossible for us to run multiple builds parallel to each other.

So, as posters before me have already stated on a more theoretical level, this should showcase some potential (and likely) side-implications a large build usually has outside of needing more space on the harddrive.
> 3 votes

---
Tags: builds
---


# Question
Title: Jenkins - Scripted Pipeline - Input String
I am struggling to set up an input step in a **scripted** Jenkins pipeline that will let me as the user to input a string.

Scenario: I am building a Docker image. I want to ask the user what tags to tag the image with once it's built. I want the user to supply a comma separated list like so: latest,0.0.4,some-tag-name

All I have right now is an input asking the user if the core image should be built:

```
  def buildCoreImage = input(
    message: 'Build Core Image?',
    ok: 'Yes',
    parameters: [
      booleanParam(defaultValue: true, description: 'Push the button to build core image.',name: 'Yes?')
    ]
  )

  echo "Build core?:" + buildCoreImage

```

So in theory it should be as easy as changing the booleanParam to a stringParam, BUT the documentation does not have it: Jenkins - Pipeline: Input Step

Thanks for your time!

# Answer
After some more research I found the answer:

```
  def coreImageTags = input(
    id: 'coreImageTags', message: 'Enter a comma separated list of additional tags for the image (0.0.1,some-tagname,etc):?',
    parameters: [
      [$class: 'StringParameterDefinition', defaultValue: 'None', description: 'List of tags', name: 'coreImageTagsList'],
    ]
  )

  echo ("Image tags: "+coreImageTags)

```

**Important note**

It is stated in the documentation but I want to point it out specifically: If you copy/paste my solution here, `coreImageTags` will contain a string directly. If you do multiple parameters like so:

```
    parameters: [
      [$class: 'StringParameterDefinition', defaultValue: 'None', description: 'List of tags', name: 'coreImageTagsList'],
      [$class: 'StringParameterDefinition', defaultValue: 'None', description: 'Something else', name: 'somethingElse'],
    ]

```

You will not get a single values but an array of values:

```
  echo ("Image tags: "+coreImageTags['coreImageTagsList'])
  echo ("Image tags: "+coreImageTags['somethingElse'])

```

The following posts will help:

stackoverflow.com read-interactive-input-in-jenkins-pipeline-to-a-variable

CloudBees - Pipeline-How-to-manage-user-inputs

A list of classes you can use in this way and what they do is in the Jenkins Input-Step documentation: Pipeline - Input Step
> 2 votes

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