In a team where Node and Golang were the language of choice, we used GitHub private repos for code, TeamCity as the driver for CI/CD and Salt to deploy the Docker images to our different environments running on AWS EC2 instances. I must say I really liked TeamCity and its different integrations with GitHub, build processes (Node/NPM, frontend tooling, ..) and how variables could be shared down with project and releases.

To deploy code with Salt, we had an SSH account on the Salt server configured with a bunch of deploy keys. Each of those had a forced command that would read $SSH_ORIGINAL_COMMAND and forward this information to an agent (running as root) that would execute Salt with the correct arguments, based on information in $SSH_ORIGINAL_COMMAND. This let us use a build step in TeamCity that basically did ssh deploy@mgmt-gateway [env] [project] [version]. Deployments were logged to New Relic and Slack.

In a different team that are fond of PHP we use a private GitLab CE for code management, GitLab CI Multi-runner as the build agent for CI/CD, Ansible for configuration management and code deploys to different environments running on AWS EC2. Like in the previous team, we have configured our .gitlab-ci.yml to pass some arguments in $SSH_ORIGINAL_COMMAND over SSH to a management node that in turns talks to Ansible.

Something I like with having a private GitLab CE instance is that development doesn't stop because your public Git host is DDoSed or have other problems (like the recently discussed one here on HN).

Test and staging servers are shutdown/destroyed off-hours and restarted/recreated by cron jobs that execute Ansible plays which identify eligible EC2 instances via EC2 tags. Production environments with multiple servers are similarly scaled down during off-hours. By simply modifying/removing the "shutdown" tag from the AWS resources, teams are able to exclude their test/staging environments from the scheduled shutdowns, something which is useful for upcoming releases. ;)

In the Node/Golang shop I loved how simple Docker images were and how good it felt to deploy it to isolated containers. Unfortunately, I don't see how that's possible (in a clean way, preferrably without using two images) when both an Nginx process (static file serving, e.g. frontend resources) and a PHP-FPM process needs access to the same code release.

(If you have experience with Nginx/PHP-FPM apps and Docker, feel free to enlighten me!)

Things I'm not entirely fond of about GitLab CI is that:

- each branch in each repo must have a .gitlab-ci.yml that is up-to-date (administrative challenge!)

- it's entirely driven from a git push (though the web gui provides buttons for existing builds to retry/manually execute steps to e.g. deploy code)

GitLab has no support for a centrally managed .gitlab-ci.yml file on a project group and/or project level. There's no way to define variables on a project group and/or project level. There's no way to schedule jobs so that you can execute daily/weekly tests, or to manage jobs (in a user-friendly way via the web gui) that perform cron-like tasks, so you can avoid putting these tasks on the server themselves in /etc/cron.d (which becomes a problem when you restore backups / bake AMIs / do auto-scaling).

I'd love to look more into K8 and Google's cloud offerings, especially since I believe this might be the future and because I believe Google are lightyears ahead of the competition when it comes to security and protecting the privacy of its customers. Unfortunately I'm afraid it's not viable given my team's current investment in Nginx/PHP-FPM apps and various AWS services.