If you had a clean slate, how would you go about setting up your CI/CD for a brand new web application? What tools would you choose, what would your process look like? What pitfalls would you avoid?
With respect to CI you're spoiled for choice now compared to just a 4-5 years ago when these cloud providers like CircleCI and travis did not exist. Jenkins is still the most flexible in my opinion but requires you to be a bit more serious in terms of putting on your build engineer 'hat'.
If you host privately then bitbucket offers their CI called pipeline. 
Gitlab has their own CI. 
Then there is always travis-ci. 
Jenkins  is great, but I thought it was a little much for my pet projects.
In the end I decided to make one of my side projects a mini-CI/CD, appropriately called minici . Since then I have rolled most of the side projects over to this.
All of these play well with docker (to a degree). Mini-ci (my baby) was built with docker in mind.
Things to watch out for: Each of the CI systems have a flavor of runner file or DSL to run in their CI. This is sometime a YAML file or in Jenkins case a groovy script. In my mini-ci project I opted for a standard Makefile with a specific target name to kick things off.
None of them have a steep learning curve, but I find that the complexity creeps in when you want a full SDLC pipeline with multiple stages, reporting, and alerting. Lots of moving parts.
I'm glad that I put time into learning modern CI/CD systems. It has made me more comfortable to put down a side projects for months at a time and only ship tiny changes without worry of remembering how to do deployments or run tests.
 - https://bitbucket.org/product/features/pipelines
 - https://about.gitlab.com/features/gitlab-ci-cd/
 - https://travis-ci.org
 - https://jenkins.io
 - https://github.com/undernewmanagement/mini-ci
Continuous Deployment for Serverless Applications
Then you can just use Docker Swarm/Rancher/etc for deployment.