├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── meta └── main.yml ├── screenshots ├── 3_boxes.png ├── Windows_build_number_Docker_failing.png ├── Windows_build_number_Docker_working.png ├── all-apps-available-via-routing-mesh.png ├── curl-linux-container.png ├── docker-network-correct-nat-config.png ├── docker-service-inspect-app.png ├── docker-service-ls.png ├── docker-service-ps-app.png ├── docker-swarm-services-registered-eureka.png ├── docker-swarm-setup.png ├── first-docker-swarm-services-running-portainer.png ├── first-full-call-through-traefik-mixed-os-apps-incl-eureka-feign-soapui-client.png ├── first-successful-Linux-worker-join-with-ansible.png ├── first-successful-ansible-run-to-hybrid-linux-windows-machines.png ├── first-successful-app-call-through-traefik.png ├── first-successful-call-to-both-windows-and-linux-containers-through-traefik.png ├── first-successful-docker-swarm-join-with-ansible.png ├── first-successful-docker-swarm-join.png ├── first-successful-docker-windows-ingress-swarm-service.png ├── first-successful-push-into-registry.png ├── first-successful-stack-deploy.png ├── first-successful-traefik-service-deployment-incl-registered-apps.png ├── how-swarm-services-work.png ├── ingress-routing-mesh.png ├── portainer-swarm-visualizer.png ├── running-hybrid-os-docker-swarm-windows-linux-manager-and-windows-linux-worker-nodes.png ├── spring-boot-example-running-docker-windows-containers.png ├── spring-cloud-example-running-docker-windows-containers-docker-compose.png ├── spring-cloud-example-running-docker-windows-containers.png ├── windows-docker-network-architecture.png └── working-build-nr-and-update-kb4048955-for-ingress-networking-docker-windows.png ├── step0-packer-windows-vagrantbox ├── README.md ├── ansible-windows-simple │ ├── group_vars │ │ └── windows-dev.yml │ ├── hostsfile │ └── windows-playbook.yml ├── automated_windows_installation.png ├── packerCommands.sh ├── scripts │ ├── Autounattend.xml │ ├── configure-ansible.ps1 │ ├── oracle-cert.cer │ ├── server_1709 │ │ └── Autounattend.xml │ ├── server_1803 │ │ └── Autounattend.xml │ └── vm-guest-tools.bat ├── vagrantfile-windows_1709-multimachine.template ├── vagrantfile-windows_1803-multimachine.template ├── vagrantfile-windows_2016-multimachine.template ├── vagrantfile-windows_2016.template └── windows_server_2016_docker.json ├── step1-prepare-docker-windows ├── build-springboot-oraclejre-nanoserver-image.yml ├── check-build-number.yml ├── group_vars │ └── all.yml ├── hostsfile ├── install-docker-compose.yml ├── install-docker.yml ├── install-windows-container-features.yml ├── install-windows-updates.yml ├── playbookCommands.sh ├── prepare-docker-windows.yml ├── run-test-container.yml └── templates │ ├── Dockerfile-SpringBoot-OracleJRE-Nanoserver-1709.j2 │ ├── Dockerfile-SpringBoot-OracleJRE-Nanoserver-1803.j2 │ └── Dockerfile-SpringBoot-OracleJRE-Nanoserver.j2 ├── step2-single-spring-boot-app ├── ansible-windows-docker-springboot.yml ├── group_vars │ ├── all.yml │ ├── ansible-windows-docker-springboot-dev.yml │ └── ansible-windows-docker-springboot-qa.yml ├── hostsfile ├── playbookCommands.sh └── templates │ └── Dockerfile-SpringBoot-App.j2 ├── step3-multiple-spring-boot-apps-docker-compose ├── ansible-windows-docker-springboot.yml ├── docker-compose-run-all-services.yml ├── group_vars │ ├── all.yml │ ├── ansible-windows-docker-springboot-dev.yml │ └── ansible-windows-docker-springboot-qa.yml ├── hostsfile ├── playbookCommands.sh ├── spring-boot-app-health-check.yml ├── spring-boot-app-prepare.yml └── templates │ ├── Dockerfile-SpringBoot-App.j2 │ └── docker-compose.j2 ├── step4-windows-linux-multimachine-vagrant-docker-swarm-setup ├── Vagrantfile ├── allow-http-docker-registry.yml ├── display-swarm-status.yml ├── group_vars │ ├── all.yml │ ├── linux.yml │ ├── masterlinux.yml │ ├── masterwindows.yml │ ├── windows.yml │ ├── workerlinux.yml │ └── workerwindows.yml ├── hostsfile ├── initialize-docker-swarm.yml ├── initialize-swarm-and-join-all-nodes.yml ├── label-os-specific-nodes.yml ├── playbookCommands.sh ├── prepare-docker-linux.yml ├── prepare-docker-nodes.yml ├── prepare-firewalls-for-swarm.yml ├── run-portainer.yml ├── run-swarm-registry.yml └── templates │ └── daemon.j2 └── step5-deploy-multiple-spring-boot-apps-to-mixed-os-docker-swarm ├── build-and-deploy-apps-2-swarm.yml ├── deploy-services-swarm.yml ├── group_vars ├── all.yml ├── linux.yml ├── masterlinux.yml ├── masterwindows.yml ├── windows.yml ├── workerlinux.yml └── workerwindows.yml ├── hostsfile ├── playbookCommands.sh ├── prepare-docker-images-linux.yml ├── prepare-docker-images-windows.yml ├── prepare-firewall-app-access.yml ├── spring-boot-app-health-check.yml └── templates ├── Dockerfile-SpringBoot-Linux.j2 ├── Dockerfile-SpringBoot-Windows.j2 └── docker-stack.j2 /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Package Files # 4 | *.jar 5 | *.war 6 | *.ear 7 | 8 | # Eclipse # 9 | .settings 10 | .project 11 | .classpath 12 | .studio 13 | target 14 | 15 | # Vagrant 16 | .vagrant 17 | 18 | # Apple # 19 | .DS_Store 20 | 21 | # Intellij # 22 | .idea 23 | *.iml 24 | *.log 25 | 26 | # Ansible 27 | *.retry 28 | 29 | # logback 30 | logback.out.xml 31 | 32 | # zips 33 | *.tar.gz 34 | 35 | # Vagrantboxes 36 | *.box 37 | step0-packer-windows-vagrantbox/Vagrantfile 38 | *.ISO 39 | step0-packer-windows-vagrantbox/packer_cache 40 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | --- 2 | language: python 3 | python: "2.7" 4 | 5 | # Use the new container infrastructure 6 | sudo: false 7 | 8 | # Install ansible 9 | addons: 10 | apt: 11 | packages: 12 | - python-pip 13 | 14 | install: 15 | # Install ansible 16 | - pip install ansible 17 | 18 | # Check ansible version 19 | - ansible --version 20 | 21 | # Create ansible.cfg with correct roles_path 22 | - printf '[defaults]\nroles_path=../' >ansible.cfg 23 | 24 | script: 25 | # Basic playbook syntax check 26 | - ansible-playbook -i hostsfile step1-prepare-docker-windows/prepare-docker-windows.yml --extra-vars "host=ansible-windows-docker-springboot-dev" --syntax-check 27 | - ansible-playbook -i hostsfile step2-single-spring-boot-app/ansible-windows-docker-springboot.yml --extra-vars "host=ansible-windows-docker-springboot-dev" --syntax-check 28 | - ansible-playbook -i hostsfile step3-multiple-spring-boot-apps-docker-compose/ansible-windows-docker-springboot.yml --extra-vars "host=ansible-windows-docker-springboot-dev" --syntax-check 29 | - ansible-playbook -i hostsfile step4-windows-linux-multimachine-vagrant-docker-swarm-setup/prepare-docker-nodes.yml --syntax-check 30 | - ansible-playbook -i hostsfile step4-windows-linux-multimachine-vagrant-docker-swarm-setup/initialize-docker-swarm.yml --syntax-check 31 | - ansible-playbook -i hostsfile step5-deploy-multiple-spring-boot-apps-to-mixed-os-docker-swarm/build-and-deploy-apps-2-swarm.yml --syntax-check 32 | 33 | notifications: 34 | webhooks: https://galaxy.ansible.com/api/v1/notifications/ 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Jonas Hecht 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /meta/main.yml: -------------------------------------------------------------------------------- 1 | galaxy_info: 2 | author: Jonas Hecht 3 | description: Ansible playbook to deploy and run Spring Boot apps with Docker natively on Windows. 4 | # company: your company (optional) 5 | 6 | license: license (MIT) 7 | 8 | min_ansible_version: 2.3.0 9 | 10 | github_branch: release 11 | 12 | # 13 | # Below are all platforms currently available. Just uncomment 14 | # the ones that apply to your role. If you don't see your 15 | # platform on this list, let us know and we'll get it added! 16 | # 17 | platforms: 18 | #- name: EL 19 | # versions: 20 | # - all 21 | # - 5 22 | # - 6 23 | # - 7 24 | #- name: GenericUNIX 25 | # versions: 26 | # - all 27 | # - any 28 | #- name: OpenBSD 29 | # versions: 30 | # - all 31 | # - 5.6 32 | # - 5.7 33 | # - 5.8 34 | # - 5.9 35 | # - 6.0 36 | #- name: Fedora 37 | # versions: 38 | # - all 39 | # - 16 40 | # - 17 41 | # - 18 42 | # - 19 43 | # - 20 44 | # - 21 45 | # - 22 46 | # - 23 47 | #- name: opensuse 48 | # versions: 49 | # - all 50 | # - 12.1 51 | # - 12.2 52 | # - 12.3 53 | # - 13.1 54 | # - 13.2 55 | #- name: MacOSX 56 | # versions: 57 | # - all 58 | # - 10.10 59 | # - 10.11 60 | # - 10.12 61 | # - 10.7 62 | # - 10.8 63 | # - 10.9 64 | #- name: IOS 65 | # versions: 66 | # - all 67 | # - any 68 | #- name: Solaris 69 | # versions: 70 | # - all 71 | # - 10 72 | # - 11.0 73 | # - 11.1 74 | # - 11.2 75 | # - 11.3 76 | #- name: SmartOS 77 | # versions: 78 | # - all 79 | # - any 80 | #- name: eos 81 | # versions: 82 | # - all 83 | # - Any 84 | - name: Windows 85 | versions: 86 | - 10 87 | - 2016 88 | #- name: Amazon 89 | # versions: 90 | # - all 91 | # - 2013.03 92 | # - 2013.09 93 | #- name: GenericBSD 94 | # versions: 95 | # - all 96 | # - any 97 | #- name: Junos 98 | # versions: 99 | # - all 100 | # - any 101 | #- name: FreeBSD 102 | # versions: 103 | # - all 104 | # - 10.0 105 | # - 10.1 106 | # - 10.2 107 | # - 10.3 108 | # - 8.0 109 | # - 8.1 110 | # - 8.2 111 | # - 8.3 112 | # - 8.4 113 | # - 9.0 114 | # - 9.1 115 | # - 9.1 116 | # - 9.2 117 | # - 9.3 118 | #- name: Ubuntu 119 | # versions: 120 | # - all 121 | # - lucid 122 | # - maverick 123 | # - natty 124 | # - oneiric 125 | # - precise 126 | # - quantal 127 | # - raring 128 | # - saucy 129 | # - trusty 130 | # - utopic 131 | # - vivid 132 | # - wily 133 | # - xenial 134 | #- name: SLES 135 | # versions: 136 | # - all 137 | # - 10SP3 138 | # - 10SP4 139 | # - 11 140 | # - 11SP1 141 | # - 11SP2 142 | # - 11SP3 143 | # - 11SP4 144 | # - 12 145 | # - 12SP1 146 | #- name: GenericLinux 147 | # versions: 148 | # - all 149 | # - any 150 | #- name: NXOS 151 | # versions: 152 | # - all 153 | # - any 154 | #- name: Debian 155 | # versions: 156 | # - all 157 | # - etch 158 | # - jessie 159 | # - lenny 160 | # - sid 161 | # - squeeze 162 | # - stretch 163 | # - wheezy 164 | 165 | galaxy_tags: 166 | 167 | - windows 168 | - windowsserver 169 | - spring 170 | - springboot 171 | - java 172 | - java8 173 | - system 174 | - development 175 | - web 176 | 177 | dependencies: [] 178 | -------------------------------------------------------------------------------- /screenshots/3_boxes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonashackt/ansible-windows-docker-springboot/614ce574de4a671e76bccf10a71416f675974e21/screenshots/3_boxes.png -------------------------------------------------------------------------------- /screenshots/Windows_build_number_Docker_failing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonashackt/ansible-windows-docker-springboot/614ce574de4a671e76bccf10a71416f675974e21/screenshots/Windows_build_number_Docker_failing.png -------------------------------------------------------------------------------- /screenshots/Windows_build_number_Docker_working.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonashackt/ansible-windows-docker-springboot/614ce574de4a671e76bccf10a71416f675974e21/screenshots/Windows_build_number_Docker_working.png -------------------------------------------------------------------------------- /screenshots/all-apps-available-via-routing-mesh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonashackt/ansible-windows-docker-springboot/614ce574de4a671e76bccf10a71416f675974e21/screenshots/all-apps-available-via-routing-mesh.png -------------------------------------------------------------------------------- /screenshots/curl-linux-container.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonashackt/ansible-windows-docker-springboot/614ce574de4a671e76bccf10a71416f675974e21/screenshots/curl-linux-container.png -------------------------------------------------------------------------------- /screenshots/docker-network-correct-nat-config.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonashackt/ansible-windows-docker-springboot/614ce574de4a671e76bccf10a71416f675974e21/screenshots/docker-network-correct-nat-config.png -------------------------------------------------------------------------------- /screenshots/docker-service-inspect-app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonashackt/ansible-windows-docker-springboot/614ce574de4a671e76bccf10a71416f675974e21/screenshots/docker-service-inspect-app.png -------------------------------------------------------------------------------- /screenshots/docker-service-ls.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonashackt/ansible-windows-docker-springboot/614ce574de4a671e76bccf10a71416f675974e21/screenshots/docker-service-ls.png -------------------------------------------------------------------------------- /screenshots/docker-service-ps-app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonashackt/ansible-windows-docker-springboot/614ce574de4a671e76bccf10a71416f675974e21/screenshots/docker-service-ps-app.png -------------------------------------------------------------------------------- /screenshots/docker-swarm-services-registered-eureka.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonashackt/ansible-windows-docker-springboot/614ce574de4a671e76bccf10a71416f675974e21/screenshots/docker-swarm-services-registered-eureka.png -------------------------------------------------------------------------------- /screenshots/docker-swarm-setup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonashackt/ansible-windows-docker-springboot/614ce574de4a671e76bccf10a71416f675974e21/screenshots/docker-swarm-setup.png -------------------------------------------------------------------------------- /screenshots/first-docker-swarm-services-running-portainer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonashackt/ansible-windows-docker-springboot/614ce574de4a671e76bccf10a71416f675974e21/screenshots/first-docker-swarm-services-running-portainer.png -------------------------------------------------------------------------------- /screenshots/first-full-call-through-traefik-mixed-os-apps-incl-eureka-feign-soapui-client.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonashackt/ansible-windows-docker-springboot/614ce574de4a671e76bccf10a71416f675974e21/screenshots/first-full-call-through-traefik-mixed-os-apps-incl-eureka-feign-soapui-client.png -------------------------------------------------------------------------------- /screenshots/first-successful-Linux-worker-join-with-ansible.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonashackt/ansible-windows-docker-springboot/614ce574de4a671e76bccf10a71416f675974e21/screenshots/first-successful-Linux-worker-join-with-ansible.png -------------------------------------------------------------------------------- /screenshots/first-successful-ansible-run-to-hybrid-linux-windows-machines.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonashackt/ansible-windows-docker-springboot/614ce574de4a671e76bccf10a71416f675974e21/screenshots/first-successful-ansible-run-to-hybrid-linux-windows-machines.png -------------------------------------------------------------------------------- /screenshots/first-successful-app-call-through-traefik.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonashackt/ansible-windows-docker-springboot/614ce574de4a671e76bccf10a71416f675974e21/screenshots/first-successful-app-call-through-traefik.png -------------------------------------------------------------------------------- /screenshots/first-successful-call-to-both-windows-and-linux-containers-through-traefik.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonashackt/ansible-windows-docker-springboot/614ce574de4a671e76bccf10a71416f675974e21/screenshots/first-successful-call-to-both-windows-and-linux-containers-through-traefik.png -------------------------------------------------------------------------------- /screenshots/first-successful-docker-swarm-join-with-ansible.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonashackt/ansible-windows-docker-springboot/614ce574de4a671e76bccf10a71416f675974e21/screenshots/first-successful-docker-swarm-join-with-ansible.png -------------------------------------------------------------------------------- /screenshots/first-successful-docker-swarm-join.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonashackt/ansible-windows-docker-springboot/614ce574de4a671e76bccf10a71416f675974e21/screenshots/first-successful-docker-swarm-join.png -------------------------------------------------------------------------------- /screenshots/first-successful-docker-windows-ingress-swarm-service.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonashackt/ansible-windows-docker-springboot/614ce574de4a671e76bccf10a71416f675974e21/screenshots/first-successful-docker-windows-ingress-swarm-service.png -------------------------------------------------------------------------------- /screenshots/first-successful-push-into-registry.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonashackt/ansible-windows-docker-springboot/614ce574de4a671e76bccf10a71416f675974e21/screenshots/first-successful-push-into-registry.png -------------------------------------------------------------------------------- /screenshots/first-successful-stack-deploy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonashackt/ansible-windows-docker-springboot/614ce574de4a671e76bccf10a71416f675974e21/screenshots/first-successful-stack-deploy.png -------------------------------------------------------------------------------- /screenshots/first-successful-traefik-service-deployment-incl-registered-apps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonashackt/ansible-windows-docker-springboot/614ce574de4a671e76bccf10a71416f675974e21/screenshots/first-successful-traefik-service-deployment-incl-registered-apps.png -------------------------------------------------------------------------------- /screenshots/how-swarm-services-work.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonashackt/ansible-windows-docker-springboot/614ce574de4a671e76bccf10a71416f675974e21/screenshots/how-swarm-services-work.png -------------------------------------------------------------------------------- /screenshots/ingress-routing-mesh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonashackt/ansible-windows-docker-springboot/614ce574de4a671e76bccf10a71416f675974e21/screenshots/ingress-routing-mesh.png -------------------------------------------------------------------------------- /screenshots/portainer-swarm-visualizer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonashackt/ansible-windows-docker-springboot/614ce574de4a671e76bccf10a71416f675974e21/screenshots/portainer-swarm-visualizer.png -------------------------------------------------------------------------------- /screenshots/running-hybrid-os-docker-swarm-windows-linux-manager-and-windows-linux-worker-nodes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonashackt/ansible-windows-docker-springboot/614ce574de4a671e76bccf10a71416f675974e21/screenshots/running-hybrid-os-docker-swarm-windows-linux-manager-and-windows-linux-worker-nodes.png -------------------------------------------------------------------------------- /screenshots/spring-boot-example-running-docker-windows-containers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonashackt/ansible-windows-docker-springboot/614ce574de4a671e76bccf10a71416f675974e21/screenshots/spring-boot-example-running-docker-windows-containers.png -------------------------------------------------------------------------------- /screenshots/spring-cloud-example-running-docker-windows-containers-docker-compose.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonashackt/ansible-windows-docker-springboot/614ce574de4a671e76bccf10a71416f675974e21/screenshots/spring-cloud-example-running-docker-windows-containers-docker-compose.png -------------------------------------------------------------------------------- /screenshots/spring-cloud-example-running-docker-windows-containers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonashackt/ansible-windows-docker-springboot/614ce574de4a671e76bccf10a71416f675974e21/screenshots/spring-cloud-example-running-docker-windows-containers.png -------------------------------------------------------------------------------- /screenshots/windows-docker-network-architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonashackt/ansible-windows-docker-springboot/614ce574de4a671e76bccf10a71416f675974e21/screenshots/windows-docker-network-architecture.png -------------------------------------------------------------------------------- /screenshots/working-build-nr-and-update-kb4048955-for-ingress-networking-docker-windows.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonashackt/ansible-windows-docker-springboot/614ce574de4a671e76bccf10a71416f675974e21/screenshots/working-build-nr-and-update-kb4048955-for-ingress-networking-docker-windows.png -------------------------------------------------------------------------------- /step0-packer-windows-vagrantbox/README.md: -------------------------------------------------------------------------------- 1 | Ansible ready & packer.io build Windows Server 2016 Vagrant box 2 | ====================================================================================== 3 | #### packer template and some Powershell scripts to build a Ansible-ready Windows Server 2016 Vagrant box (as alternative to the [Vagrant box with Windows 10 from the Microsoft Edge developer site](https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/#downloads), which doesn´t work with Docker because of the wrong build number) 4 | 5 | The box has Ansible-connectitity "turned on" (so WinRM, Firewall settings, Network settings and so on) and is a working basis for a Docker Windows Container installment. 6 | 7 | It borrowes bits from https://github.com/StefanScherer/docker-windows-box and https://github.com/StefanScherer/packer-windows, which forks https://github.com/joefitzgerald/packer-windows itself. If you like to dig deeper into the myriads of configuration options, have a look into Stefan Scherers GitHub repositories. kudos go to [Stefan](https://github.com/StefanScherer) und [Joe](Joe Fitzgerald) - and not to forget the great [hashicorp tools](https://www.hashicorp.com/). 8 | 9 | This setup will install Windows into a Virtual Box image completely without user interaction: 10 | 11 | ![automated_windows_installation](https://github.com/jonashackt/ansible-windows-docker-springboot/blob/master/step0-packer-windows-vagrantbox/automated_windows_installation.png) -------------------------------------------------------------------------------- /step0-packer-windows-vagrantbox/ansible-windows-simple/group_vars/windows-dev.yml: -------------------------------------------------------------------------------- 1 | # http://docs.ansible.com/ansible/intro_windows.html#windows-how-does-it-work 2 | 3 | ansible_user: vagrant 4 | ansible_password: vagrant 5 | ansible_port: 55986 # not 5986, as we would use for non-virtualized environments 6 | ansible_connection: winrm 7 | 8 | # The following is necessary for Python 2.7.9+ when using default WinRM self-signed certificates: 9 | ansible_winrm_server_cert_validation: ignore -------------------------------------------------------------------------------- /step0-packer-windows-vagrantbox/ansible-windows-simple/hostsfile: -------------------------------------------------------------------------------- 1 | [windows-dev] 2 | 127.0.0.1 -------------------------------------------------------------------------------- /step0-packer-windows-vagrantbox/ansible-windows-simple/windows-playbook.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: "{{host}}" 3 | 4 | tasks: 5 | - name: Install firefox 6 | win_chocolatey: 7 | name: firefox -------------------------------------------------------------------------------- /step0-packer-windows-vagrantbox/automated_windows_installation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonashackt/ansible-windows-docker-springboot/614ce574de4a671e76bccf10a71416f675974e21/step0-packer-windows-vagrantbox/automated_windows_installation.png -------------------------------------------------------------------------------- /step0-packer-windows-vagrantbox/packerCommands.sh: -------------------------------------------------------------------------------- 1 | 2 | # Run Packer build with Windows Server 2016 3 | packer build -var iso_url=Windows_Server_2016_Datacenter_EVAL_en-us_14393_refresh.ISO -var iso_checksum=70721288bbcdfe3239d8f8c0fae55f1f windows_server_2016_docker.json 4 | 5 | # add it to local Vagrant Boxes 6 | vagrant box add --name windows_2016_multimachine windows_2016_docker_multimachine_virtualbox.box 7 | 8 | 9 | # Run packer build with Windows Server 1709 10 | packer build -var iso_url=en_windows_server_version_1709_x64_dvd_100090904.iso -var iso_checksum=7c73ce30c3975652262f794fc35127b5 -var template_url=vagrantfile-windows_1709-multimachine.template -var box_output_prefix=windows_1709_docker_multimachine windows_server_2016_docker.json 11 | 12 | # add it to local Vagrant Boxes 13 | vagrant box add --name windows_1709_docker_multimachine windows_1709_docker_multimachine_virtualbox.box 14 | 15 | 16 | # Run packer build with Windows Server 1803 17 | packer build -var iso_url=en_windows_server_version_1803_x64_dvd_12063476.iso -var iso_checksum=e34b375e0b9438d72e6305f36b125406 -var template_url=vagrantfile-windows_1803-multimachine.template -var box_output_prefix=windows_1803_docker_multimachine windows_server_2016_docker.json 18 | 19 | # add it to local Vagrant Boxes 20 | vagrant box add --name windows_1803_docker_multimachine windows_1803_docker_multimachine_virtualbox.box 21 | 22 | -------------------------------------------------------------------------------- /step0-packer-windows-vagrantbox/scripts/Autounattend.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 1 11 | Primary 12 | true 13 | 14 | 15 | 16 | 17 | false 18 | NTFS 19 | C 20 | 1 21 | 1 22 | 23 | 24 | 25 | 0 26 | true 27 | 28 | OnError 29 | 30 | 31 | true 32 | Vagrant Administrator 33 | Vagrant Inc. 34 | 35 | 47 | 48 | 49 | NPPR9-FWDCX-D2C8J-H872K-2YT43 50 | Never 51 | 52 | 53 | 54 | 55 | 56 | 0 57 | 1 58 | 59 | OnError 60 | false 61 | 62 | 63 | /IMAGE/NAME 64 | Windows Server 2016 SERVERSTANDARD 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | en-US 73 | 74 | en-US 75 | en-US 76 | en-US 77 | en-US 78 | en-US 79 | 80 | 81 | 82 | 83 | false 84 | 85 | 86 | 87 | 88 | 89 | 90 | vagrant 91 | true</PlainText> 92 | </AdministratorPassword> 93 | <LocalAccounts> 94 | <LocalAccount wcm:action="add"> 95 | <Password> 96 | <Value>vagrant</Value> 97 | <PlainText>true</PlainText> 98 | </Password> 99 | <Description>Vagrant User</Description> 100 | <DisplayName>vagrant</DisplayName> 101 | <Group>administrators</Group> 102 | <Name>vagrant</Name> 103 | </LocalAccount> 104 | </LocalAccounts> 105 | </UserAccounts> 106 | <OOBE> 107 | <HideEULAPage>true</HideEULAPage> 108 | <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE> 109 | <NetworkLocation>Home</NetworkLocation> 110 | <ProtectYourPC>1</ProtectYourPC> 111 | </OOBE> 112 | <AutoLogon> 113 | <Password> 114 | <Value>vagrant</Value> 115 | <PlainText>true</PlainText> 116 | </Password> 117 | <Username>vagrant</Username> 118 | <Enabled>true</Enabled> 119 | </AutoLogon> 120 | <FirstLogonCommands> 121 | <SynchronousCommand wcm:action="add"> 122 | <CommandLine>cmd.exe /c powershell -Command "Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force"</CommandLine> 123 | <Description>Set Execution Policy 64 Bit</Description> 124 | <Order>1</Order> 125 | <RequiresUserInput>true</RequiresUserInput> 126 | </SynchronousCommand> 127 | <SynchronousCommand wcm:action="add"> 128 | <CommandLine>C:\Windows\SysWOW64\cmd.exe /c powershell -Command "Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force"</CommandLine> 129 | <Description>Set Execution Policy 32 Bit</Description> 130 | <Order>2</Order> 131 | <RequiresUserInput>true</RequiresUserInput> 132 | </SynchronousCommand> 133 | <SynchronousCommand wcm:action="add"> 134 | <CommandLine>cmd.exe /c reg add "HKLM\System\CurrentControlSet\Control\Network\NewNetworkWindowOff"</CommandLine> 135 | <Description>Network prompt</Description> 136 | <Order>3</Order> 137 | <RequiresUserInput>true</RequiresUserInput> 138 | </SynchronousCommand> 139 | <SynchronousCommand wcm:action="add"> 140 | <CommandLine>cmd.exe /c winrm quickconfig -q</CommandLine> 141 | <Description>winrm quickconfig -q</Description> 142 | <Order>5</Order> 143 | <RequiresUserInput>true</RequiresUserInput> 144 | </SynchronousCommand> 145 | <SynchronousCommand wcm:action="add"> 146 | <CommandLine>cmd.exe /c winrm quickconfig -transport:http</CommandLine> 147 | <Description>winrm quickconfig -transport:http</Description> 148 | <Order>6</Order> 149 | <RequiresUserInput>true</RequiresUserInput> 150 | </SynchronousCommand> 151 | <SynchronousCommand wcm:action="add"> 152 | <CommandLine>cmd.exe /c winrm set winrm/config @{MaxTimeoutms="1800000"}</CommandLine> 153 | <Description>Win RM MaxTimoutms</Description> 154 | <Order>7</Order> 155 | <RequiresUserInput>true</RequiresUserInput> 156 | </SynchronousCommand> 157 | <SynchronousCommand wcm:action="add"> 158 | <CommandLine>cmd.exe /c winrm set winrm/config/winrs @{MaxMemoryPerShellMB="800"}</CommandLine> 159 | <Description>Win RM MaxMemoryPerShellMB</Description> 160 | <Order>8</Order> 161 | <RequiresUserInput>true</RequiresUserInput> 162 | </SynchronousCommand> 163 | <SynchronousCommand wcm:action="add"> 164 | <CommandLine>cmd.exe /c winrm set winrm/config/service @{AllowUnencrypted="true"}</CommandLine> 165 | <Description>Win RM AllowUnencrypted</Description> 166 | <Order>9</Order> 167 | <RequiresUserInput>true</RequiresUserInput> 168 | </SynchronousCommand> 169 | <SynchronousCommand wcm:action="add"> 170 | <CommandLine>cmd.exe /c winrm set winrm/config/service/auth @{Basic="true"}</CommandLine> 171 | <Description>Win RM auth Basic</Description> 172 | <Order>10</Order> 173 | <RequiresUserInput>true</RequiresUserInput> 174 | </SynchronousCommand> 175 | <SynchronousCommand wcm:action="add"> 176 | <CommandLine>cmd.exe /c winrm set winrm/config/client/auth @{Basic="true"}</CommandLine> 177 | <Description>Win RM client auth Basic</Description> 178 | <Order>11</Order> 179 | <RequiresUserInput>true</RequiresUserInput> 180 | </SynchronousCommand> 181 | <SynchronousCommand wcm:action="add"> 182 | <CommandLine>cmd.exe /c winrm set winrm/config/listener?Address=*+Transport=HTTP @{Port="5985"} </CommandLine> 183 | <Description>Win RM listener Address/Port</Description> 184 | <Order>12</Order> 185 | <RequiresUserInput>true</RequiresUserInput> 186 | </SynchronousCommand> 187 | <SynchronousCommand wcm:action="add"> 188 | <CommandLine>cmd.exe /c netsh advfirewall firewall set rule group="remote administration" new enable=yes </CommandLine> 189 | <Description>Win RM adv firewall enable</Description> 190 | <Order>13</Order> 191 | <RequiresUserInput>true</RequiresUserInput> 192 | </SynchronousCommand> 193 | <SynchronousCommand wcm:action="add"> 194 | <CommandLine>cmd.exe /c netsh firewall add portopening TCP 5985 "Port 5985" </CommandLine> 195 | <Description>Win RM port open</Description> 196 | <Order>14</Order> 197 | <RequiresUserInput>true</RequiresUserInput> 198 | </SynchronousCommand> 199 | <SynchronousCommand wcm:action="add"> 200 | <CommandLine>cmd.exe /c net stop winrm </CommandLine> 201 | <Description>Stop Win RM Service </Description> 202 | <Order>15</Order> 203 | <RequiresUserInput>true</RequiresUserInput> 204 | </SynchronousCommand> 205 | <SynchronousCommand wcm:action="add"> 206 | <CommandLine>cmd.exe /c sc config winrm start= auto</CommandLine> 207 | <Description>Win RM Autostart</Description> 208 | <Order>16</Order> 209 | <RequiresUserInput>true</RequiresUserInput> 210 | </SynchronousCommand> 211 | <SynchronousCommand wcm:action="add"> 212 | <CommandLine>cmd.exe /c net start winrm</CommandLine> 213 | <Description>Start Win RM Service</Description> 214 | <Order>17</Order> 215 | <RequiresUserInput>true</RequiresUserInput> 216 | </SynchronousCommand> 217 | <SynchronousCommand wcm:action="add"> 218 | <CommandLine>%SystemRoot%\System32\reg.exe ADD HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ /v HideFileExt /t REG_DWORD /d 0 /f</CommandLine> 219 | <Order>18</Order> 220 | <Description>Show file extensions in Explorer</Description> 221 | </SynchronousCommand> 222 | <SynchronousCommand wcm:action="add"> 223 | <CommandLine>%SystemRoot%\System32\reg.exe ADD HKCU\Console /v QuickEdit /t REG_DWORD /d 1 /f</CommandLine> 224 | <Order>19</Order> 225 | <Description>Enable QuickEdit mode</Description> 226 | </SynchronousCommand> 227 | <SynchronousCommand wcm:action="add"> 228 | <CommandLine>%SystemRoot%\System32\reg.exe ADD HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ /v Start_ShowRun /t REG_DWORD /d 1 /f</CommandLine> 229 | <Order>20</Order> 230 | <Description>Show Run command in Start Menu</Description> 231 | </SynchronousCommand> 232 | <SynchronousCommand wcm:action="add"> 233 | <CommandLine>%SystemRoot%\System32\reg.exe ADD HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ /v StartMenuAdminTools /t REG_DWORD /d 1 /f</CommandLine> 234 | <Order>21</Order> 235 | <Description>Show Administrative Tools in Start Menu</Description> 236 | </SynchronousCommand> 237 | <SynchronousCommand wcm:action="add"> 238 | <CommandLine>%SystemRoot%\System32\reg.exe ADD HKLM\SYSTEM\CurrentControlSet\Control\Power\ /v HibernateFileSizePercent /t REG_DWORD /d 0 /f</CommandLine> 239 | <Order>22</Order> 240 | <Description>Zero Hibernation File</Description> 241 | </SynchronousCommand> 242 | <SynchronousCommand wcm:action="add"> 243 | <CommandLine>%SystemRoot%\System32\reg.exe ADD HKLM\SYSTEM\CurrentControlSet\Control\Power\ /v HibernateEnabled /t REG_DWORD /d 0 /f</CommandLine> 244 | <Order>23</Order> 245 | <Description>Disable Hibernation Mode</Description> 246 | </SynchronousCommand> 247 | <SynchronousCommand wcm:action="add"> 248 | <CommandLine>cmd.exe /c wmic useraccount where "name='vagrant'" set PasswordExpires=FALSE</CommandLine> 249 | <Order>24</Order> 250 | <Description>Disable password expiration for vagrant user</Description> 251 | </SynchronousCommand> 252 | </FirstLogonCommands> 253 | <ShowWindowsLive>false</ShowWindowsLive> 254 | </component> 255 | </settings> 256 | <settings pass="specialize"> 257 | <component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"> 258 | <OEMInformation> 259 | <HelpCustomized>false</HelpCustomized> 260 | </OEMInformation> 261 | <!-- Rename computer here. --> 262 | <ComputerName>vagrant-10</ComputerName> 263 | <TimeZone>Pacific Standard Time</TimeZone> 264 | <RegisteredOwner/> 265 | </component> 266 | <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-Security-SPP-UX" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"> 267 | <SkipAutoActivation>true</SkipAutoActivation> 268 | </component> 269 | </settings> 270 | <cpi:offlineImage xmlns:cpi="urn:schemas-microsoft-com:cpi" cpi:source="catalog:d:/sources/install_windows 7 ENTERPRISE.clg"/> 271 | </unattend> 272 | -------------------------------------------------------------------------------- /step0-packer-windows-vagrantbox/scripts/configure-ansible.ps1: -------------------------------------------------------------------------------- 1 | iwr https://raw.githubusercontent.com/ansible/ansible/devel/examples/scripts/ConfigureRemotingForAnsible.ps1 -UseBasicParsing | iex 2 | -------------------------------------------------------------------------------- /step0-packer-windows-vagrantbox/scripts/oracle-cert.cer: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonashackt/ansible-windows-docker-springboot/614ce574de4a671e76bccf10a71416f675974e21/step0-packer-windows-vagrantbox/scripts/oracle-cert.cer -------------------------------------------------------------------------------- /step0-packer-windows-vagrantbox/scripts/server_1709/Autounattend.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="utf-8"?> 2 | <unattend xmlns="urn:schemas-microsoft-com:unattend"> 3 | <servicing/> 4 | <settings pass="windowsPE"> 5 | <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"> 6 | <DiskConfiguration> 7 | <Disk wcm:action="add"> 8 | <CreatePartitions> 9 | <CreatePartition wcm:action="add"> 10 | <Order>1</Order> 11 | <Type>Primary</Type> 12 | <Extend>true</Extend> 13 | </CreatePartition> 14 | </CreatePartitions> 15 | <ModifyPartitions> 16 | <ModifyPartition wcm:action="add"> 17 | <Extend>false</Extend> 18 | <Format>NTFS</Format> 19 | <Letter>C</Letter> 20 | <Order>1</Order> 21 | <PartitionID>1</PartitionID> 22 | <Label>Windows 1709</Label> 23 | </ModifyPartition> 24 | </ModifyPartitions> 25 | <DiskID>0</DiskID> 26 | <WillWipeDisk>true</WillWipeDisk> 27 | </Disk> 28 | <WillShowUI>OnError</WillShowUI> 29 | </DiskConfiguration> 30 | <UserData> 31 | <AcceptEula>true</AcceptEula> 32 | <FullName>Vagrant Administrator</FullName> 33 | <Organization>Vagrant Inc.</Organization> 34 | 35 | <!-- 36 | NOTE: If you are re-configuring this for use of a retail key 37 | and using a retail ISO, you need to adjust the <ProductKey> block 38 | below to look like this: 39 | 40 | <ProductKey> 41 | <Key>33PXH-7Y6KF-2VJC9-XBBR8-HVTHH</Key> 42 | <WillShowUI>Never</WillShowUI> 43 | </ProductKey> 44 | 45 | Notice the addition of the `<Key>` element. 46 | --> 47 | 48 | <!-- Product Key from http://technet.microsoft.com/en-us/library/jj612867.aspx --> 49 | <ProductKey>NPPR9-FWDCX-D2C8J-H872K-2YT43 50 | <WillShowUI>Never</WillShowUI> 51 | </ProductKey> 52 | </UserData> 53 | <ImageInstall> 54 | <OSImage> 55 | <InstallTo> 56 | <DiskID>0</DiskID> 57 | <PartitionID>2</PartitionID> 58 | </InstallTo> 59 | <InstallFrom> 60 | <MetaData wcm:action="add"> 61 | <Key>/IMAGE/NAME</Key> 62 | <Value>Windows Server 2016 SERVERDATACENTERACORE</Value> 63 | </MetaData> 64 | </InstallFrom> 65 | </OSImage> 66 | </ImageInstall> 67 | </component> 68 | <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-International-Core-WinPE" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"> 69 | <SetupUILanguage> 70 | <UILanguage>en-US</UILanguage> 71 | </SetupUILanguage> 72 | <InputLocale>en-US</InputLocale> 73 | <SystemLocale>en-US</SystemLocale> 74 | <UILanguage>en-US</UILanguage> 75 | <UILanguageFallback>en-US</UILanguageFallback> 76 | <UserLocale>en-US</UserLocale> 77 | </component> 78 | </settings> 79 | <settings pass="offlineServicing"> 80 | <component name="Microsoft-Windows-LUA-Settings" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"> 81 | <EnableLUA>false</EnableLUA> 82 | </component> 83 | </settings> 84 | <settings pass="oobeSystem"> 85 | <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"> 86 | <UserAccounts> 87 | <AdministratorPassword> 88 | <Value>vagrant</Value> 89 | <PlainText>true</PlainText> 90 | </AdministratorPassword> 91 | <LocalAccounts> 92 | <LocalAccount wcm:action="add"> 93 | <Password> 94 | <Value>vagrant</Value> 95 | <PlainText>true</PlainText> 96 | </Password> 97 | <Description>Vagrant User</Description> 98 | <DisplayName>vagrant</DisplayName> 99 | <Group>administrators</Group> 100 | <Name>vagrant</Name> 101 | </LocalAccount> 102 | </LocalAccounts> 103 | </UserAccounts> 104 | <OOBE> 105 | <HideEULAPage>true</HideEULAPage> 106 | <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE> 107 | <NetworkLocation>Home</NetworkLocation> 108 | <ProtectYourPC>1</ProtectYourPC> 109 | </OOBE> 110 | <AutoLogon> 111 | <Password> 112 | <Value>vagrant</Value> 113 | <PlainText>true</PlainText> 114 | </Password> 115 | <Username>vagrant</Username> 116 | <Enabled>true</Enabled> 117 | </AutoLogon> 118 | <FirstLogonCommands> 119 | <SynchronousCommand wcm:action="add"> 120 | <CommandLine>cmd.exe /c powershell -Command "Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force"</CommandLine> 121 | <Description>Set Execution Policy 64 Bit</Description> 122 | <Order>1</Order> 123 | <RequiresUserInput>true</RequiresUserInput> 124 | </SynchronousCommand> 125 | <SynchronousCommand wcm:action="add"> 126 | <CommandLine>C:\Windows\SysWOW64\cmd.exe /c powershell -Command "Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force"</CommandLine> 127 | <Description>Set Execution Policy 32 Bit</Description> 128 | <Order>2</Order> 129 | <RequiresUserInput>true</RequiresUserInput> 130 | </SynchronousCommand> 131 | <SynchronousCommand wcm:action="add"> 132 | <CommandLine>cmd.exe /c reg add "HKLM\System\CurrentControlSet\Control\Network\NewNetworkWindowOff"</CommandLine> 133 | <Description>Network prompt</Description> 134 | <Order>3</Order> 135 | <RequiresUserInput>true</RequiresUserInput> 136 | </SynchronousCommand> 137 | <SynchronousCommand wcm:action="add"> 138 | <CommandLine>cmd.exe /c winrm quickconfig -q</CommandLine> 139 | <Description>winrm quickconfig -q</Description> 140 | <Order>5</Order> 141 | <RequiresUserInput>true</RequiresUserInput> 142 | </SynchronousCommand> 143 | <SynchronousCommand wcm:action="add"> 144 | <CommandLine>cmd.exe /c winrm quickconfig -transport:http</CommandLine> 145 | <Description>winrm quickconfig -transport:http</Description> 146 | <Order>6</Order> 147 | <RequiresUserInput>true</RequiresUserInput> 148 | </SynchronousCommand> 149 | <SynchronousCommand wcm:action="add"> 150 | <CommandLine>cmd.exe /c winrm set winrm/config @{MaxTimeoutms="1800000"}</CommandLine> 151 | <Description>Win RM MaxTimoutms</Description> 152 | <Order>7</Order> 153 | <RequiresUserInput>true</RequiresUserInput> 154 | </SynchronousCommand> 155 | <SynchronousCommand wcm:action="add"> 156 | <CommandLine>cmd.exe /c winrm set winrm/config/winrs @{MaxMemoryPerShellMB="800"}</CommandLine> 157 | <Description>Win RM MaxMemoryPerShellMB</Description> 158 | <Order>8</Order> 159 | <RequiresUserInput>true</RequiresUserInput> 160 | </SynchronousCommand> 161 | <SynchronousCommand wcm:action="add"> 162 | <CommandLine>cmd.exe /c winrm set winrm/config/service @{AllowUnencrypted="true"}</CommandLine> 163 | <Description>Win RM AllowUnencrypted</Description> 164 | <Order>9</Order> 165 | <RequiresUserInput>true</RequiresUserInput> 166 | </SynchronousCommand> 167 | <SynchronousCommand wcm:action="add"> 168 | <CommandLine>cmd.exe /c winrm set winrm/config/service/auth @{Basic="true"}</CommandLine> 169 | <Description>Win RM auth Basic</Description> 170 | <Order>10</Order> 171 | <RequiresUserInput>true</RequiresUserInput> 172 | </SynchronousCommand> 173 | <SynchronousCommand wcm:action="add"> 174 | <CommandLine>cmd.exe /c winrm set winrm/config/client/auth @{Basic="true"}</CommandLine> 175 | <Description>Win RM client auth Basic</Description> 176 | <Order>11</Order> 177 | <RequiresUserInput>true</RequiresUserInput> 178 | </SynchronousCommand> 179 | <SynchronousCommand wcm:action="add"> 180 | <CommandLine>cmd.exe /c winrm set winrm/config/listener?Address=*+Transport=HTTP @{Port="5985"} </CommandLine> 181 | <Description>Win RM listener Address/Port</Description> 182 | <Order>12</Order> 183 | <RequiresUserInput>true</RequiresUserInput> 184 | </SynchronousCommand> 185 | <SynchronousCommand wcm:action="add"> 186 | <CommandLine>cmd.exe /c netsh advfirewall firewall set rule group="remote administration" new enable=yes </CommandLine> 187 | <Description>Win RM adv firewall enable</Description> 188 | <Order>13</Order> 189 | <RequiresUserInput>true</RequiresUserInput> 190 | </SynchronousCommand> 191 | <SynchronousCommand wcm:action="add"> 192 | <CommandLine>cmd.exe /c netsh firewall add portopening TCP 5985 "Port 5985" </CommandLine> 193 | <Description>Win RM port open</Description> 194 | <Order>14</Order> 195 | <RequiresUserInput>true</RequiresUserInput> 196 | </SynchronousCommand> 197 | <SynchronousCommand wcm:action="add"> 198 | <CommandLine>cmd.exe /c net stop winrm </CommandLine> 199 | <Description>Stop Win RM Service </Description> 200 | <Order>15</Order> 201 | <RequiresUserInput>true</RequiresUserInput> 202 | </SynchronousCommand> 203 | <SynchronousCommand wcm:action="add"> 204 | <CommandLine>cmd.exe /c sc config winrm start= auto</CommandLine> 205 | <Description>Win RM Autostart</Description> 206 | <Order>16</Order> 207 | <RequiresUserInput>true</RequiresUserInput> 208 | </SynchronousCommand> 209 | <SynchronousCommand wcm:action="add"> 210 | <CommandLine>cmd.exe /c net start winrm</CommandLine> 211 | <Description>Start Win RM Service</Description> 212 | <Order>17</Order> 213 | <RequiresUserInput>true</RequiresUserInput> 214 | </SynchronousCommand> 215 | <SynchronousCommand wcm:action="add"> 216 | <CommandLine>%SystemRoot%\System32\reg.exe ADD HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ /v HideFileExt /t REG_DWORD /d 0 /f</CommandLine> 217 | <Order>18</Order> 218 | <Description>Show file extensions in Explorer</Description> 219 | </SynchronousCommand> 220 | <SynchronousCommand wcm:action="add"> 221 | <CommandLine>%SystemRoot%\System32\reg.exe ADD HKCU\Console /v QuickEdit /t REG_DWORD /d 1 /f</CommandLine> 222 | <Order>19</Order> 223 | <Description>Enable QuickEdit mode</Description> 224 | </SynchronousCommand> 225 | <SynchronousCommand wcm:action="add"> 226 | <CommandLine>%SystemRoot%\System32\reg.exe ADD HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ /v Start_ShowRun /t REG_DWORD /d 1 /f</CommandLine> 227 | <Order>20</Order> 228 | <Description>Show Run command in Start Menu</Description> 229 | </SynchronousCommand> 230 | <SynchronousCommand wcm:action="add"> 231 | <CommandLine>%SystemRoot%\System32\reg.exe ADD HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ /v StartMenuAdminTools /t REG_DWORD /d 1 /f</CommandLine> 232 | <Order>21</Order> 233 | <Description>Show Administrative Tools in Start Menu</Description> 234 | </SynchronousCommand> 235 | <SynchronousCommand wcm:action="add"> 236 | <CommandLine>%SystemRoot%\System32\reg.exe ADD HKLM\SYSTEM\CurrentControlSet\Control\Power\ /v HibernateFileSizePercent /t REG_DWORD /d 0 /f</CommandLine> 237 | <Order>22</Order> 238 | <Description>Zero Hibernation File</Description> 239 | </SynchronousCommand> 240 | <SynchronousCommand wcm:action="add"> 241 | <CommandLine>%SystemRoot%\System32\reg.exe ADD HKLM\SYSTEM\CurrentControlSet\Control\Power\ /v HibernateEnabled /t REG_DWORD /d 0 /f</CommandLine> 242 | <Order>23</Order> 243 | <Description>Disable Hibernation Mode</Description> 244 | </SynchronousCommand> 245 | <SynchronousCommand wcm:action="add"> 246 | <CommandLine>cmd.exe /c wmic useraccount where "name='vagrant'" set PasswordExpires=FALSE</CommandLine> 247 | <Order>24</Order> 248 | <Description>Disable password expiration for vagrant user</Description> 249 | </SynchronousCommand> 250 | </FirstLogonCommands> 251 | <ShowWindowsLive>false</ShowWindowsLive> 252 | </component> 253 | </settings> 254 | <settings pass="specialize"> 255 | <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"> 256 | <OEMInformation> 257 | <HelpCustomized>false</HelpCustomized> 258 | </OEMInformation> 259 | <ComputerName>vagrant-1709</ComputerName> 260 | <TimeZone>Pacific Standard Time</TimeZone> 261 | <RegisteredOwner/> 262 | </component> 263 | <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-ServerManager-SvrMgrNc" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"> 264 | <DoNotOpenServerManagerAtLogon>true</DoNotOpenServerManagerAtLogon> 265 | </component> 266 | <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-IE-ESC" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"> 267 | <IEHardenAdmin>false</IEHardenAdmin> 268 | <IEHardenUser>false</IEHardenUser> 269 | </component> 270 | <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-OutOfBoxExperience" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"> 271 | <DoNotOpenInitialConfigurationTasksAtLogon>true</DoNotOpenInitialConfigurationTasksAtLogon> 272 | </component> 273 | <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-Security-SPP-UX" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"> 274 | <SkipAutoActivation>true</SkipAutoActivation> 275 | </component> 276 | </settings> 277 | <cpi:offlineImage xmlns:cpi="urn:schemas-microsoft-com:cpi" cpi:source="wim:c:/wim/install.wim#Windows Server 2016 SERVERSTANDARD"/> 278 | </unattend> 279 | -------------------------------------------------------------------------------- /step0-packer-windows-vagrantbox/scripts/server_1803/Autounattend.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="utf-8"?> 2 | <unattend xmlns="urn:schemas-microsoft-com:unattend"> 3 | <settings pass="windowsPE"> 4 | <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-International-Core-WinPE" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"> 5 | <SetupUILanguage> 6 | <UILanguage>en-US</UILanguage> 7 | </SetupUILanguage> 8 | <InputLocale>en-US</InputLocale> 9 | <SystemLocale>en-US</SystemLocale> 10 | <UILanguage>en-US</UILanguage> 11 | <UILanguageFallback>en-US</UILanguageFallback> 12 | <UserLocale>en-US</UserLocale> 13 | </component> 14 | <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"> 15 | <DiskConfiguration> 16 | <Disk wcm:action="add"> 17 | <CreatePartitions> 18 | <CreatePartition wcm:action="add"> 19 | <Type>Primary</Type> 20 | <Order>1</Order> 21 | <Size>350</Size> 22 | </CreatePartition> 23 | <CreatePartition wcm:action="add"> 24 | <Order>2</Order> 25 | <Type>Primary</Type> 26 | <Extend>true</Extend> 27 | </CreatePartition> 28 | </CreatePartitions> 29 | <ModifyPartitions> 30 | <ModifyPartition wcm:action="add"> 31 | <Active>true</Active> 32 | <Format>NTFS</Format> 33 | <Label>boot</Label> 34 | <Order>1</Order> 35 | <PartitionID>1</PartitionID> 36 | </ModifyPartition> 37 | <ModifyPartition wcm:action="add"> 38 | <Format>NTFS</Format> 39 | <Label>Windows 1803</Label> 40 | <Letter>C</Letter> 41 | <Order>2</Order> 42 | <PartitionID>2</PartitionID> 43 | </ModifyPartition> 44 | </ModifyPartitions> 45 | <DiskID>0</DiskID> 46 | <WillWipeDisk>true</WillWipeDisk> 47 | </Disk> 48 | </DiskConfiguration> 49 | <ImageInstall> 50 | <OSImage> 51 | <InstallFrom> 52 | <MetaData wcm:action="add"> 53 | <Key>/IMAGE/NAME </Key> 54 | <Value>Windows Server 2016 SERVERDATACENTERACORE</Value> 55 | </MetaData> 56 | </InstallFrom> 57 | <InstallTo> 58 | <DiskID>0</DiskID> 59 | <PartitionID>2</PartitionID> 60 | </InstallTo> 61 | </OSImage> 62 | </ImageInstall> 63 | <UserData> 64 | <ProductKey> 65 | <!-- enter product key --> 66 | <Key></Key> 67 | <WillShowUI>OnError</WillShowUI> 68 | </ProductKey> 69 | <AcceptEula>true</AcceptEula> 70 | <FullName>Vagrant</FullName> 71 | <Organization>Vagrant</Organization> 72 | </UserData> 73 | </component> 74 | </settings> 75 | <settings pass="specialize"> 76 | <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"> 77 | <OEMInformation> 78 | <HelpCustomized>false</HelpCustomized> 79 | </OEMInformation> 80 | <ComputerName>vagrant-1803</ComputerName> 81 | <TimeZone>Pacific Standard Time</TimeZone> 82 | <RegisteredOwner/> 83 | </component> 84 | <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-ServerManager-SvrMgrNc" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"> 85 | <DoNotOpenServerManagerAtLogon>true</DoNotOpenServerManagerAtLogon> 86 | </component> 87 | <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-IE-ESC" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"> 88 | <IEHardenAdmin>false</IEHardenAdmin> 89 | <IEHardenUser>false</IEHardenUser> 90 | </component> 91 | <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-OutOfBoxExperience" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"> 92 | <DoNotOpenInitialConfigurationTasksAtLogon>true</DoNotOpenInitialConfigurationTasksAtLogon> 93 | </component> 94 | <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-Security-SPP-UX" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"> 95 | <SkipAutoActivation>true</SkipAutoActivation> 96 | </component> 97 | </settings> 98 | <settings pass="oobeSystem"> 99 | <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"> 100 | <AutoLogon> 101 | <Password> 102 | <Value>vagrant</Value> 103 | <PlainText>true</PlainText> 104 | </Password> 105 | <Enabled>true</Enabled> 106 | <Username>vagrant</Username> 107 | </AutoLogon> 108 | <FirstLogonCommands> 109 | <SynchronousCommand wcm:action="add"> 110 | <CommandLine>cmd.exe /c powershell -Command "Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force"</CommandLine> 111 | <Description>Set Execution Policy 64 Bit</Description> 112 | <Order>1</Order> 113 | <RequiresUserInput>true</RequiresUserInput> 114 | </SynchronousCommand> 115 | <SynchronousCommand wcm:action="add"> 116 | <CommandLine>C:\Windows\SysWOW64\cmd.exe /c powershell -Command "Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force"</CommandLine> 117 | <Description>Set Execution Policy 32 Bit</Description> 118 | <Order>2</Order> 119 | <RequiresUserInput>true</RequiresUserInput> 120 | </SynchronousCommand> 121 | <SynchronousCommand wcm:action="add"> 122 | <CommandLine>C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -File a:\disable-winrm.ps1</CommandLine> 123 | <Description>Disable WinRM</Description> 124 | <Order>3</Order> 125 | <RequiresUserInput>true</RequiresUserInput> 126 | </SynchronousCommand> 127 | <SynchronousCommand wcm:action="add"> 128 | <CommandLine>%SystemRoot%\System32\reg.exe ADD HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ /v HideFileExt /t REG_DWORD /d 0 /f</CommandLine> 129 | <Order>4</Order> 130 | <Description>Show file extensions in Explorer</Description> 131 | </SynchronousCommand> 132 | <SynchronousCommand wcm:action="add"> 133 | <CommandLine>%SystemRoot%\System32\reg.exe ADD HKCU\Console /v QuickEdit /t REG_DWORD /d 1 /f</CommandLine> 134 | <Order>5</Order> 135 | <Description>Enable QuickEdit mode</Description> 136 | </SynchronousCommand> 137 | <SynchronousCommand wcm:action="add"> 138 | <CommandLine>%SystemRoot%\System32\reg.exe ADD HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ /v Start_ShowRun /t REG_DWORD /d 1 /f</CommandLine> 139 | <Order>6</Order> 140 | <Description>Show Run command in Start Menu</Description> 141 | </SynchronousCommand> 142 | <SynchronousCommand wcm:action="add"> 143 | <CommandLine>%SystemRoot%\System32\reg.exe ADD HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ /v StartMenuAdminTools /t REG_DWORD /d 1 /f</CommandLine> 144 | <Order>7</Order> 145 | <Description>Show Administrative Tools in Start Menu</Description> 146 | </SynchronousCommand> 147 | <SynchronousCommand wcm:action="add"> 148 | <CommandLine>%SystemRoot%\System32\reg.exe ADD HKLM\SYSTEM\CurrentControlSet\Control\Power\ /v HibernateFileSizePercent /t REG_DWORD /d 0 /f</CommandLine> 149 | <Order>8</Order> 150 | <Description>Zero Hibernation File</Description> 151 | </SynchronousCommand> 152 | <SynchronousCommand wcm:action="add"> 153 | <CommandLine>%SystemRoot%\System32\reg.exe ADD HKLM\SYSTEM\CurrentControlSet\Control\Power\ /v HibernateEnabled /t REG_DWORD /d 0 /f</CommandLine> 154 | <Order>9</Order> 155 | <Description>Disable Hibernation Mode</Description> 156 | </SynchronousCommand> 157 | <SynchronousCommand wcm:action="add"> 158 | <CommandLine>cmd.exe /c wmic useraccount where "name='vagrant'" set PasswordExpires=FALSE</CommandLine> 159 | <Order>10</Order> 160 | <Description>Disable password expiration for vagrant user</Description> 161 | </SynchronousCommand> 162 | <!-- WITHOUT WINDOWS UPDATES --> 163 | <SynchronousCommand wcm:action="add"> 164 | <CommandLine>cmd.exe /c winrm quickconfig -q</CommandLine> 165 | <Description>winrm quickconfig -q</Description> 166 | <Order>5</Order> 167 | <RequiresUserInput>true</RequiresUserInput> 168 | </SynchronousCommand> 169 | <SynchronousCommand wcm:action="add"> 170 | <CommandLine>cmd.exe /c winrm quickconfig -transport:http</CommandLine> 171 | <Description>winrm quickconfig -transport:http</Description> 172 | <Order>6</Order> 173 | <RequiresUserInput>true</RequiresUserInput> 174 | </SynchronousCommand> 175 | <SynchronousCommand wcm:action="add"> 176 | <CommandLine>cmd.exe /c winrm set winrm/config @{MaxTimeoutms="1800000"}</CommandLine> 177 | <Description>Win RM MaxTimoutms</Description> 178 | <Order>7</Order> 179 | <RequiresUserInput>true</RequiresUserInput> 180 | </SynchronousCommand> 181 | <SynchronousCommand wcm:action="add"> 182 | <CommandLine>cmd.exe /c winrm set winrm/config/winrs @{MaxMemoryPerShellMB="800"}</CommandLine> 183 | <Description>Win RM MaxMemoryPerShellMB</Description> 184 | <Order>8</Order> 185 | <RequiresUserInput>true</RequiresUserInput> 186 | </SynchronousCommand> 187 | <SynchronousCommand wcm:action="add"> 188 | <CommandLine>cmd.exe /c winrm set winrm/config/service @{AllowUnencrypted="true"}</CommandLine> 189 | <Description>Win RM AllowUnencrypted</Description> 190 | <Order>9</Order> 191 | <RequiresUserInput>true</RequiresUserInput> 192 | </SynchronousCommand> 193 | <SynchronousCommand wcm:action="add"> 194 | <CommandLine>cmd.exe /c winrm set winrm/config/service/auth @{Basic="true"}</CommandLine> 195 | <Description>Win RM auth Basic</Description> 196 | <Order>10</Order> 197 | <RequiresUserInput>true</RequiresUserInput> 198 | </SynchronousCommand> 199 | <SynchronousCommand wcm:action="add"> 200 | <CommandLine>cmd.exe /c winrm set winrm/config/client/auth @{Basic="true"}</CommandLine> 201 | <Description>Win RM client auth Basic</Description> 202 | <Order>11</Order> 203 | <RequiresUserInput>true</RequiresUserInput> 204 | </SynchronousCommand> 205 | <SynchronousCommand wcm:action="add"> 206 | <CommandLine>cmd.exe /c winrm set winrm/config/listener?Address=*+Transport=HTTP @{Port="5985"} </CommandLine> 207 | <Description>Win RM listener Address/Port</Description> 208 | <Order>12</Order> 209 | <RequiresUserInput>true</RequiresUserInput> 210 | </SynchronousCommand> 211 | <SynchronousCommand wcm:action="add"> 212 | <CommandLine>cmd.exe /c netsh advfirewall firewall set rule group="remote administration" new enable=yes </CommandLine> 213 | <Description>Win RM adv firewall enable</Description> 214 | <Order>13</Order> 215 | <RequiresUserInput>true</RequiresUserInput> 216 | </SynchronousCommand> 217 | <SynchronousCommand wcm:action="add"> 218 | <CommandLine>cmd.exe /c netsh firewall add portopening TCP 5985 "Port 5985" </CommandLine> 219 | <Description>Win RM port open</Description> 220 | <Order>14</Order> 221 | <RequiresUserInput>true</RequiresUserInput> 222 | </SynchronousCommand> 223 | <SynchronousCommand wcm:action="add"> 224 | <CommandLine>cmd.exe /c net stop winrm </CommandLine> 225 | <Description>Stop Win RM Service </Description> 226 | <Order>15</Order> 227 | <RequiresUserInput>true</RequiresUserInput> 228 | </SynchronousCommand> 229 | <SynchronousCommand wcm:action="add"> 230 | <CommandLine>cmd.exe /c sc config winrm start= auto</CommandLine> 231 | <Description>Win RM Autostart</Description> 232 | <Order>16</Order> 233 | <RequiresUserInput>true</RequiresUserInput> 234 | </SynchronousCommand> 235 | <SynchronousCommand wcm:action="add"> 236 | <CommandLine>cmd.exe /c net start winrm</CommandLine> 237 | <Description>Start Win RM Service</Description> 238 | <Order>17</Order> 239 | <RequiresUserInput>true</RequiresUserInput> 240 | </SynchronousCommand> 241 | <!-- END WITHOUT WINDOWS UPDATES --> 242 | 243 | </FirstLogonCommands> 244 | <OOBE> 245 | <HideEULAPage>true</HideEULAPage> 246 | <HideLocalAccountScreen>true</HideLocalAccountScreen> 247 | <HideOEMRegistrationScreen>true</HideOEMRegistrationScreen> 248 | <HideOnlineAccountScreens>true</HideOnlineAccountScreens> 249 | <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE> 250 | <NetworkLocation>Home</NetworkLocation> 251 | <ProtectYourPC>1</ProtectYourPC> 252 | </OOBE> 253 | <UserAccounts> 254 | <AdministratorPassword> 255 | <Value>vagrant</Value> 256 | <PlainText>true</PlainText> 257 | </AdministratorPassword> 258 | <LocalAccounts> 259 | <LocalAccount wcm:action="add"> 260 | <Password> 261 | <Value>vagrant</Value> 262 | <PlainText>true</PlainText> 263 | </Password> 264 | <Group>administrators</Group> 265 | <DisplayName>Vagrant</DisplayName> 266 | <Name>vagrant</Name> 267 | <Description>Vagrant User</Description> 268 | </LocalAccount> 269 | </LocalAccounts> 270 | </UserAccounts> 271 | <RegisteredOwner/> 272 | </component> 273 | </settings> 274 | <settings pass="offlineServicing"> 275 | <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-LUA-Settings" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"> 276 | <EnableLUA>false</EnableLUA> 277 | </component> 278 | </settings> 279 | <cpi:offlineImage xmlns:cpi="urn:schemas-microsoft-com:cpi" cpi:source="wim:c:/wim/install.wim#Windows Server 2016 SERVERSTANDARD"/> 280 | </unattend> -------------------------------------------------------------------------------- /step0-packer-windows-vagrantbox/scripts/vm-guest-tools.bat: -------------------------------------------------------------------------------- 1 | :: Install 7zip 2 | if not exist "C:\Windows\Temp\7z920-x64.msi" ( 3 | powershell -Command "(New-Object System.Net.WebClient).DownloadFile('http://www.7-zip.org/a/7z920-x64.msi', 'C:\Windows\Temp\7z920-x64.msi')" <NUL 4 | ) 5 | msiexec /qb /i C:\Windows\Temp\7z920-x64.msi 6 | 7 | :: There needs to be Oracle CA (Certificate Authority) certificates installed in order 8 | :: to prevent user intervention popups which will undermine a silent installation. 9 | cmd /c certutil -addstore -f "TrustedPublisher" A:\oracle-cert.cer 10 | 11 | if exist "C:\Users\vagrant\VBoxGuestAdditions.iso" ( 12 | move /Y C:\Users\vagrant\VBoxGuestAdditions.iso C:\Windows\Temp 13 | ) 14 | 15 | if not exist "C:\Windows\Temp\VBoxGuestAdditions.iso" ( 16 | powershell -Command "(New-Object System.Net.WebClient).DownloadFile('http://download.virtualbox.org/virtualbox/5.2.16/VBoxGuestAdditions_5.2.16.iso', 'C:\Windows\Temp\VBoxGuestAdditions.iso')" <NUL 17 | ) 18 | 19 | cmd /c ""C:\Program Files\7-Zip\7z.exe" x C:\Windows\Temp\VBoxGuestAdditions.iso -oC:\Windows\Temp\virtualbox" 20 | certutil -addstore -f "TrustedPublisher" C:\Windows\Temp\virtualbox\cert\vbox-sha256-r3.cer 21 | certutil -addstore -f "TrustedPublisher" C:\Windows\Temp\virtualbox\cert\vbox-sha256.cer 22 | certutil -addstore -f "TrustedPublisher" C:\Windows\Temp\virtualbox\cert\vbox-sha1.cer 23 | cmd /c C:\Windows\Temp\virtualbox\VBoxWindowsAdditions.exe /S 24 | rd /S /Q "C:\Windows\Temp\virtualbox" 25 | 26 | 27 | msiexec /qb /x C:\Windows\Temp\7z920-x64.msi 28 | -------------------------------------------------------------------------------- /step0-packer-windows-vagrantbox/vagrantfile-windows_1709-multimachine.template: -------------------------------------------------------------------------------- 1 | Vagrant.configure("2") do |config| 2 | config.vm.box = "windows_1709_docker_multi" 3 | config.vm.guest = :windows 4 | 5 | config.windows.halt_timeout = 15 6 | 7 | # Configure Vagrant to use WinRM instead of SSH 8 | config.vm.communicator = "winrm" 9 | 10 | # Configure WinRM Connectivity 11 | config.winrm.username = "vagrant" 12 | config.winrm.password = "vagrant" 13 | 14 | end -------------------------------------------------------------------------------- /step0-packer-windows-vagrantbox/vagrantfile-windows_1803-multimachine.template: -------------------------------------------------------------------------------- 1 | Vagrant.configure("2") do |config| 2 | config.vm.box = "windows_1803_docker_multi" 3 | config.vm.guest = :windows 4 | 5 | config.windows.halt_timeout = 15 6 | 7 | # Configure Vagrant to use WinRM instead of SSH 8 | config.vm.communicator = "winrm" 9 | 10 | # Configure WinRM Connectivity 11 | config.winrm.username = "vagrant" 12 | config.winrm.password = "vagrant" 13 | 14 | end -------------------------------------------------------------------------------- /step0-packer-windows-vagrantbox/vagrantfile-windows_2016-multimachine.template: -------------------------------------------------------------------------------- 1 | Vagrant.configure("2") do |config| 2 | config.vm.box = "windows_2016_docker_multi" 3 | config.vm.guest = :windows 4 | 5 | config.windows.halt_timeout = 15 6 | 7 | # Configure Vagrant to use WinRM instead of SSH 8 | config.vm.communicator = "winrm" 9 | 10 | # Configure WinRM Connectivity 11 | config.winrm.username = "vagrant" 12 | config.winrm.password = "vagrant" 13 | 14 | end -------------------------------------------------------------------------------- /step0-packer-windows-vagrantbox/vagrantfile-windows_2016.template: -------------------------------------------------------------------------------- 1 | Vagrant.configure("2") do |config| 2 | config.vm.box = "windows_2016_docker" 3 | config.vm.guest = :windows 4 | 5 | config.windows.halt_timeout = 15 6 | 7 | # Configure Vagrant to use WinRM instead of SSH 8 | config.vm.communicator = "winrm" 9 | 10 | # Configure WinRM Connectivity 11 | config.winrm.username = "vagrant" 12 | config.winrm.password = "vagrant" 13 | 14 | # Forwarding the Windows Server 2016 Guest Port 8080 t0 48080 15 | # so that we can access it easily from outside the VM 16 | config.vm.network "forwarded_port", guest: 8080, host: 48080, host_ip: "127.0.0.1", id: "edgeservice" 17 | 18 | config.vm.provider "virtualbox" do |vb| 19 | vb.name = "WindowsServer2016Docker" 20 | # Display the VirtualBox GUI when booting the machine 21 | vb.gui = true 22 | # More Power for the Windows Box with Docker 23 | vb.memory = 6144 24 | vb.cpus = 4 25 | end 26 | end -------------------------------------------------------------------------------- /step0-packer-windows-vagrantbox/windows_server_2016_docker.json: -------------------------------------------------------------------------------- 1 | { 2 | "builders": [ 3 | { 4 | "vm_name":"WindowsServer2016DockerPackerBuild", 5 | "type": "virtualbox-iso", 6 | "communicator": "winrm", 7 | "iso_url": "{{user `iso_url`}}", 8 | "iso_checksum_type": "{{user `iso_checksum_type`}}", 9 | "iso_checksum": "{{user `iso_checksum`}}", 10 | "headless": false, 11 | "boot_wait": "2m", 12 | "winrm_username": "vagrant", 13 | "winrm_password": "vagrant", 14 | "winrm_timeout": "6h", 15 | "shutdown_command": "shutdown /s /t 10 /f /d p:4:1 /c \"Packer Shutdown\"", 16 | "post_shutdown_delay": "10s", 17 | "guest_os_type": "Windows2016_64", 18 | "guest_additions_mode": "attach", 19 | "disk_size": 50000, 20 | "floppy_files": [ 21 | "{{user `autounattend_file`}}", 22 | "./scripts/configure-ansible.ps1", 23 | "./scripts/oracle-cert.cer" 24 | ], 25 | "vboxmanage": [ 26 | ["modifyvm", "{{.Name}}", "--memory", "2048"], 27 | ["modifyvm", "{{.Name}}", "--cpus", "1"], 28 | ["modifyvm", "{{.Name}}", "--vram", "32"] 29 | ] 30 | } 31 | ], 32 | "provisioners": [ 33 | { 34 | "type": "windows-shell", 35 | "execute_command": "{{ .Vars }} cmd /c \"{{ .Path }}\"", 36 | "scripts": [ 37 | "./scripts/vm-guest-tools.bat" 38 | ] 39 | }, 40 | { 41 | "type": "powershell", 42 | "scripts": [ 43 | "./scripts/configure-ansible.ps1" 44 | ] 45 | } 46 | ], 47 | "post-processors": [ 48 | { 49 | "type": "vagrant", 50 | "keep_input_artifact": false, 51 | "output": "{{user `box_output_prefix`}}_{{.Provider}}.box", 52 | "vagrantfile_template": "{{user `template_url`}}" 53 | } 54 | ], 55 | "variables": { 56 | "iso_url": "https://software-download.microsoft.com/download/pr/Windows_Server_2016_Datacenter_EVAL_en-us_14393_refresh.ISO", 57 | "iso_checksum_type": "md5", 58 | "iso_checksum": "70721288BBCDFE3239D8F8C0FAE55F1F", 59 | "template_url": "vagrantfile-windows_2016.template", 60 | "box_output_prefix": "windows_2016_docker", 61 | "autounattend_file": "./scripts/Autounattend.xml" 62 | } 63 | } -------------------------------------------------------------------------------- /step1-prepare-docker-windows/build-springboot-oraclejre-nanoserver-image.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Starting to build the springboot-oraclejre-nanoserver Docker image 3 | set_fact: 4 | image_path: "C:\\{{image_name}}" 5 | 6 | - name: Create directory C:\springboot-oraclejre-nanoserver to build our image 7 | win_file: path={{image_path}} state=directory 8 | 9 | - name: Check if JRE was already downloaded 10 | win_stat: 11 | path: "{{image_path}}\\{{server_jre_name}}" 12 | register: server_jre_on_server 13 | 14 | - name: Install wget for downloading JRE 15 | win_chocolatey: 16 | name: wget 17 | when: server_jre_on_server.stat.size is undefined 18 | 19 | ### As of Ansible 2.2 there´s only win_stat module available (and not win_find) - so we have to use a win_stat.stat attribute like size to check, 20 | ### if the JRE is already downloaded - because the return values arent defined, if there´s no file, this check should work for us 21 | - name: Download Server JRE to C:\spring-boot (only if not already done before) 22 | win_shell: "wget.exe --no-cookies --no-check-certificate --header \"Cookie: oraclelicense=accept-securebackup-cookie\" \"http://download.oracle.com/otn-pub/java/jdk/8u{{java8_update_version}}-{{java_build_version}}/a58eab1ec242421181065cdc37240b08/{{server_jre_name}}\" -O {{image_path}}\\{{server_jre_name}}" 23 | when: server_jre_on_server.stat.size is undefined 24 | 25 | - name: Template and copy Spring Boot app´s Dockerfile (version 2016) to directory C:\spring-boot\spring_boot_app.name 26 | win_template: 27 | src: "templates/Dockerfile-SpringBoot-OracleJRE-Nanoserver.j2" 28 | dest: "{{image_path}}\\Dockerfile" 29 | when: windows_version == "pre-1709" 30 | 31 | - name: Template and copy Spring Boot app´s Dockerfile (version 1709) to directory C:\spring-boot\spring_boot_app.name 32 | win_template: 33 | src: "templates/Dockerfile-SpringBoot-OracleJRE-Nanoserver-1709.j2" 34 | dest: "{{image_path}}\\Dockerfile" 35 | when: windows_version == "1709" 36 | 37 | - name: Template and copy Spring Boot app´s Dockerfile (version 1803) to directory C:\spring-boot\spring_boot_app.name 38 | win_template: 39 | src: "templates/Dockerfile-SpringBoot-OracleJRE-Nanoserver-1803.j2" 40 | dest: "{{image_path}}\\Dockerfile" 41 | when: windows_version == "1803" 42 | 43 | - name: Remove older springboot-oraclejre-nanoserver Docker image (if there) 44 | win_shell: docker rmi springboot-oraclejre-nanoserver:latest --force 45 | ignore_errors: yes 46 | 47 | - name: Build springboot-oraclejre-nanoserver Docker image 48 | win_shell: docker build . --tag springboot-oraclejre-nanoserver:latest 49 | args: 50 | chdir: "{{image_path}}" -------------------------------------------------------------------------------- /step1-prepare-docker-windows/check-build-number.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Get Windows version, because the Docker Containers differ between them 3 | win_file_version: 4 | path: C:\Windows\System32\hal.dll 5 | register: hal_dll_version_return 6 | 7 | - name: Windows is 1803 8 | set_fact: 9 | windows_version: "1803" 10 | when: hal_dll_version_return.win_file_version.file_build_part == "17134" 11 | 12 | - name: Windows is 1709 (Fall Creators Update) 13 | set_fact: 14 | windows_version: "1709" 15 | when: hal_dll_version_return.win_file_version.file_build_part == "16299" 16 | 17 | - name: Windows is pre 1709 18 | set_fact: 19 | windows_version: "pre-1709" 20 | when: hal_dll_version_return.win_file_version.file_build_part == "14393" 21 | 22 | - name: Fail, if Windows Build number doesn´t support Windows Docker Containers correctly 23 | fail: 24 | msg: "Windows Build Number {{hal_dll_version_return.win_file_version.product_version}} doesn´t support Windows Docker Container correctly ({{hal_dll_version_return.win_file_version.file_private_part}} is to small)" 25 | when: (windows_version == "pre-1709") and 26 | (hal_dll_version_return.win_file_version.file_private_part|int < 206) 27 | 28 | - name: Congratulations 29 | debug: 30 | msg: "With your Build Number {{hal_dll_version_return.win_file_version.product_version}} you have choosen a good basis for Windows Docker Containers!" -------------------------------------------------------------------------------- /step1-prepare-docker-windows/group_vars/all.yml: -------------------------------------------------------------------------------- 1 | # http://docs.ansible.com/ansible/intro_windows.html#windows-how-does-it-work 2 | 3 | ansible_user: vagrant 4 | ansible_password: vagrant 5 | ansible_port: 55986 # not 5986, as we would use for non-virtualized environments 6 | ansible_connection: winrm 7 | 8 | # The following is necessary for Python 2.7.9+ when using default WinRM self-signed certificates: 9 | ansible_winrm_server_cert_validation: ignore -------------------------------------------------------------------------------- /step1-prepare-docker-windows/hostsfile: -------------------------------------------------------------------------------- 1 | [ansible-windows-docker-springboot-dev] 2 | 127.0.0.1 3 | 4 | [ansible-windows-docker-springboot-qa] 5 | 127.0.0.1 -------------------------------------------------------------------------------- /step1-prepare-docker-windows/install-docker-compose.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install (or upgrade) Docker Compose via chocolatey 3 | win_chocolatey: 4 | name: docker-compose 5 | state: latest 6 | 7 | # Because win_reboot doesnt recognize that the virtual machine is already up, we set the timeouts way lower & ignore_errors: yes 8 | - name: After fresh Docker installation we reboot our Windows box once again - it´s Windows after all and after that Docker should be ready :) (mostly this step will fail, but it should work nevertheless) 9 | win_reboot: 10 | reboot_timeout_sec: 60 11 | connect_timeout: 60 12 | ignore_errors: yes -------------------------------------------------------------------------------- /step1-prepare-docker-windows/install-docker.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Checking if Docker Windows Service is already configured (to always ensure a fresh Windows Docker installation) 3 | win_service: 4 | name: docker 5 | register: docker_service_info 6 | ignore_errors: yes 7 | 8 | - name: Stop old Docker Windows Service if there 9 | win_service: 10 | name: docker 11 | state: stopped 12 | when: docker_service_info.exists == True 13 | 14 | - name: Remove old Docker Windows Service if there 15 | win_shell: "C:\\ProgramData\\chocolatey\\lib\\docker\\tools\\docker\\dockerd.exe --unregister-service" 16 | when: docker_service_info.exists == True 17 | ignore_errors: yes 18 | 19 | - name: Install (or upgrade) Docker via chocolatey 20 | win_chocolatey: 21 | name: docker 22 | state: latest 23 | 24 | - name: Register Docker as a Windows Service 25 | win_shell: "C:\\ProgramData\\chocolatey\\lib\\docker\\tools\\docker\\dockerd.exe --register-service" 26 | ignore_errors: yes 27 | 28 | - name: Start Docker as Windows Service 29 | win_service: 30 | name: docker 31 | state: started 32 | 33 | - name: Pull the small Windows Docker Base Image microsoft/nanoserver from hub.docker.com 34 | win_shell: docker pull microsoft/nanoserver 35 | 36 | - name: Pull the small Windows Docker Base Image microsoft/nanoserver with tag 1709 from hub.docker.com 37 | win_shell: docker pull microsoft/nanoserver:1709 38 | when: windows_version == "1709" 39 | 40 | - name: Pull the small Windows Docker Base Image microsoft/nanoserver with tag 1803 from hub.docker.com 41 | win_shell: docker pull microsoft/nanoserver:1803 42 | when: windows_version == "1803" 43 | 44 | # - name: Get the second (but 10GB big) Windows Docker Base Image microsoft/windowsservercore from hub.docker.com (you may grab a coffee now...) 45 | # win_shell: docker pull microsoft/windowsservercore -------------------------------------------------------------------------------- /step1-prepare-docker-windows/install-windows-container-features.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Check if Containers are already installed as Windows Feature 3 | win_shell: Get-WindowsOptionalFeature -Online –FeatureName Containers | Where State -CContains "Enabled" 4 | register: check_feature_container_installed 5 | 6 | # Only install the feature, if not already installed 7 | # It isn´t installed, if Get-WindowsFeature –Name FeatureName | Where Installed returns an empty response 8 | - name: Install Containers natively as Windows Feature (only, if not already installed) 9 | win_shell: Enable-WindowsOptionalFeature -Online -FeatureName containers -All -NoRestart 10 | when: check_feature_container_installed.stdout == '' 11 | ignore_errors: yes 12 | register: feature_container_installation 13 | 14 | - name: Check if Hyper-V is already installed as Windows Feature 15 | win_shell: Get-WindowsOptionalFeature -Online –FeatureName Microsoft-Hyper-V | Where State -CContains "Enabled" 16 | register: check_feature_hyperv_installed 17 | 18 | - name: Install Hyper-V as Windows Feature (only, if not already installed) 19 | win_shell: Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All -NoRestart 20 | when: check_feature_hyperv_installed.stdout == '' 21 | ignore_errors: yes 22 | register: feature_hyperv_installation 23 | 24 | # Because win_reboot doesnt recognize that the virtual machine is already up, we set the timeouts way lower & ignore_errors: yes 25 | - name: When Containers and/or Hyper-V had to be installed, we have to reboot the Machine to have them take effect (mostly this step will fail, but it should work nevertheless) 26 | win_reboot: 27 | reboot_timeout_sec: 60 28 | connect_timeout: 60 29 | when: feature_container_installation.changed or feature_hyperv_installation.changed 30 | ignore_errors: yes -------------------------------------------------------------------------------- /step1-prepare-docker-windows/install-windows-updates.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install all security, critical, and rollup updates 3 | win_updates: 4 | category_names: 5 | - SecurityUpdates 6 | - CriticalUpdates 7 | - UpdateRollups 8 | reboot: yes 9 | reboot_timeout: 60 10 | 11 | 12 | # - name: Install latest PSWindowsUpdate 13 | # win_chocolatey: 14 | # name: pswindowsupdate 15 | # state: latest 16 | # 17 | # - name: Register Microsoft Update Service instead of default Windows Update Service 18 | # win_shell: "Add-WUServiceManager -ServiceID 7971f918-a847-4430-9279-4a52d1efe18d -Confirm:$false" 19 | # ignore_errors: yes 20 | # 21 | # - name: Install all Windows Updates 22 | # win_shell: Get-WUInstall –MicrosoftUpdate –AcceptAll –AutoReboot -IgnoreUserInput -WhatIf -Verbose 23 | # ignore_errors: yes -------------------------------------------------------------------------------- /step1-prepare-docker-windows/playbookCommands.sh: -------------------------------------------------------------------------------- 1 | 2 | # Check if Connection works 3 | ansible windows-dev -i hostsfile -m win_ping 4 | 5 | # Prepare Docker on Windows 6 | ansible-playbook -i hostsfile prepare-docker-windows.yml --extra-vars "host=ansible-windows-docker-springboot-dev" 7 | -------------------------------------------------------------------------------- /step1-prepare-docker-windows/prepare-docker-windows.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: "{{host}}" 3 | 4 | tasks: 5 | - name: Check the minimum Windows build number 6 | include_tasks: check-build-number.yml 7 | tags: check 8 | 9 | - name: Install Windows Containers and Hyper-V Windows Features (if not already present) 10 | include_tasks: install-windows-container-features.yml 11 | tags: dockerinstall 12 | 13 | - name: Install Docker on Windows (always the newest version) and pull needed base images 14 | include_tasks: install-docker.yml 15 | tags: dockerinstall 16 | 17 | - name: Install Docker Compose (also always the newest version) 18 | include_tasks: install-docker-compose.yml 19 | tags: dockerinstall 20 | 21 | - name: Run a Microsoft Docker Windows Testcontainer 22 | include_tasks: run-test-container.yml 23 | 24 | - name: Build the springboot-oraclejre-nanoserver Docker image 25 | include_tasks: build-springboot-oraclejre-nanoserver-image.yml 26 | vars: 27 | image_name: springboot-oraclejre-nanoserver 28 | java8_update_version: 172 29 | java_build_version: b11 30 | server_jre_name: server-jre-8u{{java8_update_version}}-windows-x64.tar.gz 31 | tags: baseimage 32 | 33 | - name: Your Windows Box is now fully ready to run Spring Boot Apps inside Windows Docker Containers 34 | debug: 35 | msg: "springboot-oraclejre8-nanoserver Docker image is ready for you Spring Boot Apps!" -------------------------------------------------------------------------------- /step1-prepare-docker-windows/run-test-container.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Run a Microsoft test docker container (Windows Server 2016) 3 | win_shell: "docker run --name dotnetbot-container microsoft/dotnet-samples:dotnetapp-nanoserver" 4 | register: docker_test_run_2016 5 | when: windows_version == "pre-1709" 6 | 7 | - name: Run a Microsoft test docker container (Windows Server Version 1709) 8 | win_shell: "docker run --name dotnetbot-container microsoft/dotnet-samples:dotnetapp-nanoserver-1709" 9 | register: docker_test_run_1709 10 | when: windows_version == "1709" 11 | 12 | - name: Run a Microsoft test docker container (Windows Server Version 1803) 13 | win_shell: "docker run --name dotnetbot-container microsoft/dotnet-samples:dotnetapp-nanoserver-1803" 14 | register: docker_test_run_1803 15 | when: windows_version == "1803" 16 | 17 | - name: Docker is ready on your 2016 Box and waiting for your Containers :) 18 | debug: 19 | msg: "{{ docker_test_run_2016.stdout_lines }} " 20 | when: windows_version == "pre-1709" 21 | 22 | - name: Docker is ready on your Box and waiting for your Containers :) 23 | debug: 24 | msg: "{{ docker_test_run_1709.stdout_lines }} " 25 | when: windows_version == "1709" 26 | 27 | - name: Docker is ready on your Box and waiting for your Containers :) 28 | debug: 29 | msg: "{{ docker_test_run_1803.stdout_lines }} " 30 | when: windows_version == "1803" 31 | 32 | - name: Remove the Microsoft test docker container 33 | win_shell: docker rm dotnetbot-container --force 34 | ignore_errors: yes 35 | -------------------------------------------------------------------------------- /step1-prepare-docker-windows/templates/Dockerfile-SpringBoot-OracleJRE-Nanoserver-1709.j2: -------------------------------------------------------------------------------- 1 | #jinja2: newline_sequence:'\r\n' 2 | # We need to use the powershell image from 1709 on, because standard nanoserver has no Powershell installed... 3 | # FROM microsoft/powershell:6.0.0-rc.2-nanoserver-1709 4 | # using windowsservercore instead of nanoserver, its the only working solution right now 5 | FROM microsoft/windowsservercore:1709 6 | 7 | # This is a base-Image for running Spring Boot Apps on Docker Windows Containers 8 | MAINTAINER Jonas Hecht 9 | 10 | # Extract Server-JRE into C:\\jdk1.8.0_xyz in the Container 11 | ADD {{server_jre_name}} / 12 | 13 | # Configure Path for easy Java usage (1709er style) 14 | ENV JAVA_HOME=C:\\jdk1.8.0_{{java8_update_version}} 15 | RUN setx PATH "%JAVA_HOME%\\bin;%PATH%" 16 | 17 | # Create logging default path for Spring Boot 18 | VOLUME C:\\tmp -------------------------------------------------------------------------------- /step1-prepare-docker-windows/templates/Dockerfile-SpringBoot-OracleJRE-Nanoserver-1803.j2: -------------------------------------------------------------------------------- 1 | #jinja2: newline_sequence:'\r\n' 2 | # We need to use the powershell image from 1709 on, because standard nanoserver has no Powershell installed... 3 | # FROM microsoft/powershell:6.0.2-nanoserver-1803 4 | # using windowsservercore instead of nanoserver, its the only working solution right now 5 | FROM microsoft/windowsservercore:1803 6 | 7 | # This is a base-Image for running Spring Boot Apps on Docker Windows Containers 8 | MAINTAINER Jonas Hecht 9 | 10 | # Extract Server-JRE into C:\\jdk1.8.0_xyz in the Container 11 | ADD {{server_jre_name}} / 12 | 13 | # Configure Path for easy Java usage (1709er style) 14 | ENV JAVA_HOME=C:\\jdk1.8.0_{{java8_update_version}} 15 | RUN setx PATH "%JAVA_HOME%\\bin;%PATH%" 16 | 17 | # Create logging default path for Spring Boot 18 | VOLUME C:\\tmp -------------------------------------------------------------------------------- /step1-prepare-docker-windows/templates/Dockerfile-SpringBoot-OracleJRE-Nanoserver.j2: -------------------------------------------------------------------------------- 1 | #jinja2: newline_sequence:'\r\n' 2 | FROM microsoft/nanoserver:latest 3 | 4 | # This is a base-Image for running Spring Boot Apps on Docker Windows Containers 5 | MAINTAINER Jonas Hecht 6 | 7 | # Extract Server-JRE into C:\\jdk1.8.0_xyz in the Container 8 | ADD {{server_jre_name}} / 9 | 10 | # Configure Path for easy Java usage (2016er style) 11 | ENV JAVA_HOME=C:\\jdk1.8.0_{{java8_update_version}} 12 | RUN setx /M PATH %PATH%;%JAVA_HOME%\bin 13 | 14 | # Create logging default path for Spring Boot 15 | VOLUME C:\\tmp 16 | 17 | # A 'Temporary workaround for Windows DNS client weirdness' randomly found at https://github.com/docker/labs/blob/master/windows/windows-containers/MultiContainerApp.md 18 | # Without this, DNS 19 | SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop';"] 20 | RUN set-itemproperty -path 'HKLM:\SYSTEM\CurrentControlSet\Services\Dnscache\Parameters' -Name ServerPriorityTimeLimit -Value 0 -Type DWord -------------------------------------------------------------------------------- /step2-single-spring-boot-app/ansible-windows-docker-springboot.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: "{{host}}" 3 | vars: 4 | base_path: "C:\\springboot\\simpleapp" 5 | app_port: 8088 6 | target_path: "{{base_path}}\\{{app_name}}" 7 | 8 | tasks: 9 | # Prepare for the Docker build... 10 | - name: Create directory C:\springboot\simpleapp\app_name, if not there 11 | win_file: path={{target_path}} state=directory 12 | 13 | - name: Template and copy Spring Boot app´s Dockerfile to directory C:\springboot\simpleapp\app_name 14 | win_template: 15 | src: "templates/Dockerfile-SpringBoot-App.j2" 16 | dest: "{{target_path}}\\Dockerfile" 17 | 18 | - name: Copy Spring Boot app´s jar-File to directory C:\springboot\simpleapp\app_name 19 | win_copy: 20 | src: "{{jar_input_path}}" 21 | dest: "{{target_path}}\\{{app_name}}.jar" 22 | 23 | # Cleanup old Docker containers & images 24 | - name: Stop the Service´ Docker container 25 | win_shell: docker stop simpleapp_{{app_name}} 26 | ignore_errors: yes 27 | 28 | - name: Remove the Service´ Docker container 29 | win_shell: docker rm simpleapp_{{app_name}} --force 30 | ignore_errors: yes 31 | 32 | - name: Remove the Service´ Docker image 33 | win_shell: docker rmi simpleapp_{{app_name}}:latest --force 34 | ignore_errors: yes 35 | 36 | # Build & run our Spring Boot App 37 | - name: Build the Service´ Docker image 38 | win_shell: docker build . --tag simpleapp_{{app_name}}:latest 39 | args: 40 | chdir: "{{target_path}}" 41 | 42 | - name: Run the Service´ Docker container 43 | win_shell: "docker run -d --publish {{app_port}}:{{app_port}} --name=simpleapp_{{app_name}} --restart=unless-stopped simpleapp_{{app_name}}:latest" 44 | 45 | # Healthcheck our Spring Boot App 46 | - name: Obtain the Docker Container´s internal IP address (because localhost doesn´t work for now https://github.com/docker/for-win/issues/458) 47 | win_shell: "docker inspect -f {% raw %}'{{ .NetworkSettings.Networks.nat.IPAddress }}' {% endraw %} simpleapp_{{app_name}} {{ '>' }} container_ip.txt" 48 | 49 | - name: Get the Docker Container´s internal IP address from the temporary txt-file (we have to do this because of templating problems, see http://stackoverflow.com/a/32279729/4964553) 50 | win_shell: cat container_ip.txt 51 | register: win_shell_txt_return 52 | 53 | - name: Define the IP as variable 54 | set_fact: 55 | docker_container_ip: "{{ win_shell_txt_return.stdout.splitlines()[0] }}" 56 | 57 | - debug: 58 | msg: "Your Docker Container has the internal IP {{ docker_container_ip }} --> Let´s do a health-check against this URI: 'http://{{ docker_container_ip }}:{{app_port}}/health'" 59 | 60 | - name: Sadly the first win_uri call responds with non-correctly filled fields - so we do a second one & ignore this error 61 | win_uri: 62 | url: "http://{{ docker_container_ip }}:{{app_port}}/health" 63 | method: GET 64 | headers: 65 | Accept: application/json 66 | register: health_result_bad 67 | until: health_result_bad.status_code == 200 68 | ignore_errors: yes 69 | 70 | - name: 71 | debug: 72 | msg: "Our first check gave us: {{ health_result_bad }}" 73 | 74 | - name: Wait until our Spring Boot app is up & running 75 | win_uri: 76 | url: "http://{{ docker_container_ip }}:{{app_port}}/health" 77 | method: GET 78 | headers: 79 | Accept: application/json 80 | register: health_result 81 | until: health_result.status_code == 200 82 | retries: 30 83 | delay: 20 84 | ignore_errors: yes -------------------------------------------------------------------------------- /step2-single-spring-boot-app/group_vars/all.yml: -------------------------------------------------------------------------------- 1 | # http://docs.ansible.com/ansible/intro_windows.html#windows-how-does-it-work 2 | 3 | ansible_port: 55986 # not 5986, as we would use for non-virtualized environments 4 | ansible_connection: winrm 5 | 6 | # The following is necessary for Python 2.7.9+ when using default WinRM self-signed certificates: 7 | ansible_winrm_server_cert_validation: ignore -------------------------------------------------------------------------------- /step2-single-spring-boot-app/group_vars/ansible-windows-docker-springboot-dev.yml: -------------------------------------------------------------------------------- 1 | # http://docs.ansible.com/ansible/intro_windows.html#windows-how-does-it-work 2 | 3 | ansible_user: vagrant 4 | ansible_password: vagrant -------------------------------------------------------------------------------- /step2-single-spring-boot-app/group_vars/ansible-windows-docker-springboot-qa.yml: -------------------------------------------------------------------------------- 1 | # http://docs.ansible.com/ansible/intro_windows.html#windows-how-does-it-work 2 | 3 | ansible_user: vagrant 4 | ansible_password: vagrant -------------------------------------------------------------------------------- /step2-single-spring-boot-app/hostsfile: -------------------------------------------------------------------------------- 1 | [ansible-windows-docker-springboot-dev] 2 | 127.0.0.1 3 | 4 | [ansible-windows-docker-springboot-qa] 5 | 127.0.0.1 -------------------------------------------------------------------------------- /step2-single-spring-boot-app/playbookCommands.sh: -------------------------------------------------------------------------------- 1 | 2 | # Run Spring Boot App on Docker Windows 3 | ansible-playbook -i hostsfile ansible-windows-docker-springboot.yml --extra-vars "host=ansible-windows-docker-springboot-dev app_name=weatherbackend jar_input_path=../../cxf-spring-cloud-netflix-docker/weatherbackend/target/weatherbackend-0.0.1-SNAPSHOT.jar" 4 | 5 | -------------------------------------------------------------------------------- /step2-single-spring-boot-app/templates/Dockerfile-SpringBoot-App.j2: -------------------------------------------------------------------------------- 1 | #jinja2: newline_sequence:'\r\n' 2 | FROM springboot-oraclejre-nanoserver:latest 3 | 4 | MAINTAINER Jonas Hecht 5 | 6 | # Expose the apps Port 7 | EXPOSE {{app_port}} 8 | 9 | # Add Spring Boot app.jar to Container 10 | ADD {{app_name}}.jar app.jar 11 | 12 | # Fire up our Spring Boot app by default 13 | CMD ["java.exe", "-jar app.jar --server.port={{app_port}}"] 14 | 15 | -------------------------------------------------------------------------------- /step3-multiple-spring-boot-apps-docker-compose/ansible-windows-docker-springboot.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: "{{host}}" 3 | vars: 4 | base_path: "C:\\springboot" 5 | services: 6 | - name: zuul-edgeservice 7 | path_to_jar: "../../cxf-spring-cloud-netflix-docker/zuul-edgeservice/target/zuul-edgeservice-0.0.1-SNAPSHOT.jar" 8 | port: 8080 9 | map_to_same_port_on_host: true 10 | service_registry_name: eureka-serviceregistry 11 | 12 | - name: eureka-serviceregistry 13 | path_to_jar: "../../cxf-spring-cloud-netflix-docker/eureka-serviceregistry/target/eureka-serviceregistry-0.0.1-SNAPSHOT.jar" 14 | port: 8761 15 | map_to_same_port_on_host: true 16 | service_registry_name: eureka-serviceregistry-second 17 | 18 | - name: eureka-serviceregistry-second 19 | path_to_jar: "../../cxf-spring-cloud-netflix-docker/eureka-serviceregistry/target/eureka-serviceregistry-0.0.1-SNAPSHOT.jar" 20 | port: 8761 21 | service_registry_name: eureka-serviceregistry 22 | 23 | - name: weatherbackend 24 | path_to_jar: "../../cxf-spring-cloud-netflix-docker/weatherbackend/target/weatherbackend-0.0.1-SNAPSHOT.jar" 25 | port: 8090 26 | service_registry_name: eureka-serviceregistry-second 27 | 28 | - name: weatherservice 29 | path_to_jar: "../../cxf-spring-cloud-netflix-docker/weatherservice/target/weatherservice-0.0.1-SNAPSHOT.jar" 30 | port: 8095 31 | service_registry_name: eureka-serviceregistry 32 | 33 | tasks: 34 | - name: Create base directory C:\springboot, if not there 35 | win_file: path={{base_path}} state=directory 36 | 37 | - name: Preparing the Spring Boot App´s Files for later docker-compose run 38 | include: spring-boot-app-prepare.yml 39 | with_items: "{{ vars.services }}" 40 | 41 | - name: Run all Services with Docker Compose 42 | include: docker-compose-run-all-services.yml 43 | 44 | - name: Do healthchecks for all services 45 | include: spring-boot-app-health-check.yml 46 | with_items: "{{ vars.services }}" -------------------------------------------------------------------------------- /step3-multiple-spring-boot-apps-docker-compose/docker-compose-run-all-services.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Template docker-compose.yml to directory C:\spring-boot 3 | win_template: 4 | src: "templates/docker-compose.j2" 5 | dest: "{{base_path}}\\docker-compose.yml" 6 | 7 | - name: Stop all Docker containers (if there) 8 | win_shell: docker-compose --project-name springboot stop 9 | args: 10 | chdir: "{{base_path}}" 11 | ignore_errors: yes 12 | 13 | - name: Remove all Docker containers (if there) 14 | win_shell: docker-compose --project-name springboot rm -f 15 | args: 16 | chdir: "{{base_path}}" 17 | ignore_errors: yes 18 | 19 | - name: Remove all Services Docker images - just to be 100% save, that everything is build from the ground up 20 | win_shell: docker-compose --project-name springboot down --rmi all 21 | args: 22 | chdir: "{{base_path}}" 23 | ignore_errors: yes 24 | 25 | - name: (Re-)Build all Docker images 26 | win_shell: docker-compose build 27 | args: 28 | chdir: "{{base_path}}" 29 | ignore_errors: yes 30 | 31 | # As we later need to know our container's names for healthchecking but also want to be able to scale out, we're not able to use 32 | # containername feature https://docs.docker.com/compose/compose-file/#containername 33 | # But there's help! With docker-compose --project-name a CustomContainerNameBeginning (https://github.com/docker/compose/issues/3722) 34 | # we'll know exactly the names of our containers, which are springboot_service.name_1 - like springboot_weatherservice_1 35 | - name: Run all Docker containers 36 | win_shell: docker-compose --project-name springboot up -d 37 | args: 38 | chdir: "{{base_path}}" 39 | register: first_compose_up_run_result 40 | ignore_errors: yes 41 | 42 | # Sadly there are situations, where the first attempt to do a docker-compose up will fail for only some of our services 43 | # with this error: 'failed to create endpoint app_xyz_1 on network nat: HNS failed with error : Unspecified error' 44 | # But as we want to have them all running, simply giving the docker-compose a second 'up' mostly fixes the problem 45 | - name: If one container failed at startup, try to run it again (e.g. with 'failed to create endpoint app_xyz_1 on network nat .. HNS failed with error .. Unspecified error') 46 | win_shell: docker-compose --project-name springboot up -d 47 | args: 48 | chdir: "{{base_path}}" 49 | when: first_compose_up_run_result|failed 50 | ignore_errors: yes -------------------------------------------------------------------------------- /step3-multiple-spring-boot-apps-docker-compose/group_vars/all.yml: -------------------------------------------------------------------------------- 1 | # http://docs.ansible.com/ansible/intro_windows.html#windows-how-does-it-work 2 | 3 | ansible_port: 55986 # not 5986, as we would use for non-virtualized environments 4 | ansible_connection: winrm 5 | 6 | # The following is necessary for Python 2.7.9+ when using default WinRM self-signed certificates: 7 | ansible_winrm_server_cert_validation: ignore -------------------------------------------------------------------------------- /step3-multiple-spring-boot-apps-docker-compose/group_vars/ansible-windows-docker-springboot-dev.yml: -------------------------------------------------------------------------------- 1 | # http://docs.ansible.com/ansible/intro_windows.html#windows-how-does-it-work 2 | 3 | ansible_user: vagrant 4 | ansible_password: vagrant -------------------------------------------------------------------------------- /step3-multiple-spring-boot-apps-docker-compose/group_vars/ansible-windows-docker-springboot-qa.yml: -------------------------------------------------------------------------------- 1 | # http://docs.ansible.com/ansible/intro_windows.html#windows-how-does-it-work 2 | 3 | ansible_user: vagrant 4 | ansible_password: vagrant -------------------------------------------------------------------------------- /step3-multiple-spring-boot-apps-docker-compose/hostsfile: -------------------------------------------------------------------------------- 1 | [ansible-windows-docker-springboot-dev] 2 | 127.0.0.1 3 | 4 | [ansible-windows-docker-springboot-qa] 5 | 127.0.0.1 -------------------------------------------------------------------------------- /step3-multiple-spring-boot-apps-docker-compose/playbookCommands.sh: -------------------------------------------------------------------------------- 1 | 2 | # Scale Spring Boot Apps on Docker Windows 3 | ansible-playbook -i hostsfile ansible-windows-docker-springboot.yml --extra-vars "host=ansible-windows-docker-springboot-dev" 4 | 5 | -------------------------------------------------------------------------------- /step3-multiple-spring-boot-apps-docker-compose/spring-boot-app-health-check.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Defining needed variables 3 | set_fact: 4 | spring_boot_app: 5 | name: "{{ item.name }}" 6 | port: "{{ item.port }}" 7 | 8 | - name: Obtain the Docker Container´s internal IP address (because localhost doesn´t work for now https://github.com/docker/for-win/issues/458) 9 | win_shell: "docker inspect -f {% raw %}'{{ .NetworkSettings.Networks.nat.IPAddress }}' {% endraw %} springboot_{{spring_boot_app.name}}_1 {{ '>' }} container_ip.txt" 10 | 11 | - name: Get the Docker Container´s internal IP address from the temporary txt-file (we have to do this because of templating problems, see http://stackoverflow.com/a/32279729/4964553) 12 | win_shell: cat container_ip.txt 13 | register: win_shell_txt_return 14 | 15 | - name: Define the IP as variable 16 | set_fact: 17 | docker_container_ip: "{{ win_shell_txt_return.stdout.splitlines()[0] }}" 18 | 19 | - debug: 20 | msg: "The Docker Container that runs your App '{{spring_boot_app.name}}' has the internal IP {{ docker_container_ip }} --> Let´s do a health-check against this URI: 'http://{{ docker_container_ip }}:{{spring_boot_app.port}}/health'" 21 | 22 | # Spring Boot Actuators strange Content-Type 'application/vnd.spring-boot.actuator.v1+json' when calling 23 | # http://appname:port/health can be avoided by using the a correct header: 'Accept: application/json' 24 | # Doing so, the app reacts with a normal 'application/json' in the response and the healthcheck run's fine again :) 25 | - name: Wait until our Spring Boot app is up & running 26 | win_uri: 27 | url: "http://{{ docker_container_ip }}:{{spring_boot_app.port}}/health" 28 | method: GET 29 | headers: 30 | Accept: application/json 31 | register: health_result 32 | until: health_result.status_code == 200 33 | retries: 30 34 | delay: 20 35 | ignore_errors: yes 36 | 37 | - name: Show some more info, only when health check went wrong 38 | win_uri: 39 | url: "http://{{ docker_container_ip }}:{{spring_boot_app.port}}/health" 40 | method: GET 41 | register: health_bad_result 42 | ignore_errors: yes 43 | when: health_result|failed 44 | 45 | - name: Show some more info, only when health check went wrong 46 | debug: 47 | msg: "The app reacted with: {{health_bad_result}}" 48 | when: health_result|failed 49 | 50 | -------------------------------------------------------------------------------- /step3-multiple-spring-boot-apps-docker-compose/spring-boot-app-prepare.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Defining needed variables 3 | set_fact: 4 | spring_boot_app: 5 | name: "{{ item.name }}" 6 | port: "{{ item.port }}" 7 | jar: "{{ item.path_to_jar }}" 8 | registry_name: "{{ item.service_registry_name }}" 9 | 10 | - name: Preparing the following Spring Boot App´s Files for docker-compose run 11 | debug: 12 | msg: "Processing '{{spring_boot_app.name}}' with port '{{ spring_boot_app.port }}'" 13 | 14 | - name: Create directory C:\springboot\spring_boot_app.name, if not there 15 | win_file: path={{base_path}}\\{{spring_boot_app.name}} state=directory 16 | 17 | - name: Template and copy Spring Boot app´s Dockerfile to directory C:\springboot\spring_boot_app.name 18 | win_template: 19 | src: "templates/Dockerfile-SpringBoot-App.j2" 20 | dest: "{{base_path}}\\{{spring_boot_app.name}}\\Dockerfile" 21 | 22 | - name: Copy Spring Boot app´s jar-File to directory C:\springboot\spring_boot_app.name 23 | win_copy: 24 | src: "{{spring_boot_app.jar}}" 25 | dest: "{{base_path}}\\{{spring_boot_app.name}}\\{{spring_boot_app.name}}.jar" 26 | -------------------------------------------------------------------------------- /step3-multiple-spring-boot-apps-docker-compose/templates/Dockerfile-SpringBoot-App.j2: -------------------------------------------------------------------------------- 1 | #jinja2: newline_sequence:'\r\n' 2 | FROM springboot-oraclejre-nanoserver:latest 3 | 4 | MAINTAINER Jonas Hecht 5 | 6 | ENV REGISTRY_HOST {{spring_boot_app.registry_name}} 7 | ENV SPRINGBOOT_APP_NAME {{spring_boot_app.name}} 8 | 9 | # Expose the apps Port 10 | EXPOSE {{spring_boot_app.port}} 11 | 12 | # Add Spring Boot app.jar to Container 13 | ADD {{spring_boot_app.name}}.jar app.jar 14 | 15 | # Fire up our Spring Boot app by default 16 | CMD ["java.exe", "-jar app.jar --server.port={{spring_boot_app.port}}"] 17 | 18 | -------------------------------------------------------------------------------- /step3-multiple-spring-boot-apps-docker-compose/templates/docker-compose.j2: -------------------------------------------------------------------------------- 1 | #jinja2: newline_sequence:'\r\n' 2 | version: '3.2' 3 | 4 | services: 5 | 6 | {% for service in vars.services %} 7 | {{ service.name }}: 8 | build: ./{{ service.name }} 9 | {% if service.map_to_same_port_on_host is defined %} 10 | ports: 11 | - "{{ service.port }}:{{ service.port }}" 12 | {% else %} 13 | ports: 14 | - "{{ service.port }}" 15 | {% endif %} 16 | tty: 17 | true 18 | restart: 19 | unless-stopped 20 | {% endfor %} 21 | 22 | networks: 23 | default: 24 | external: 25 | name: "nat" -------------------------------------------------------------------------------- /step4-windows-linux-multimachine-vagrant-docker-swarm-setup/Vagrantfile: -------------------------------------------------------------------------------- 1 | Vagrant.configure("2") do |config| 2 | 3 | # One Master / Manager Node with Linux 4 | config.vm.define "masterlinux" do |masterlinux| 5 | masterlinux.vm.box = "ubuntu/xenial64" 6 | masterlinux.vm.hostname = "masterlinux01" 7 | 8 | # Register domain test for later routing prettiness with Traefik 9 | masterlinux.dns.tld = "test" 10 | 11 | # Forwarding the port for Ansible explicitely to not run into Vagrants 'Port Collisions and Correction' 12 | # see https://www.vagrantup.com/docs/networking/forwarded_ports.html, which would lead to problems with Ansible later 13 | masterlinux.vm.network "forwarded_port", guest: 22, host: 2222, host_ip: "127.0.0.1", id: "ssh" 14 | 15 | # As to https://www.vagrantup.com/docs/multi-machine/ & https://www.vagrantup.com/docs/networking/private_network.html 16 | # we need to configure a private network, so that our machines are able to talk to one another 17 | masterlinux.vm.network "private_network", ip: "172.16.2.10" 18 | 19 | masterlinux.vm.provider :virtualbox do |virtualbox| 20 | virtualbox.name = "MasterLinuxUbuntu" 21 | virtualbox.gui = true 22 | virtualbox.memory = 2048 23 | virtualbox.cpus = 2 24 | virtualbox.customize ["modifyvm", :id, "--ioapic", "on"] 25 | virtualbox.customize ["modifyvm", :id, "--vram", "32"] 26 | # Forward DNS resolver from host (vagrant dns) to box 27 | virtualbox.customize ["modifyvm", :id, "--natdnshostresolver1", "on"] 28 | end 29 | 30 | # Forwarding the Guest to Host ports, so that we can access it easily from outside the VM 31 | masterlinux.vm.network "forwarded_port", guest: 9000, host: 49000, host_ip: "127.0.0.1", id: "portainer" 32 | masterlinux.vm.network "forwarded_port", guest: 8080, host: 48080, host_ip: "127.0.0.1", id: "traefik_dashboard" 33 | masterlinux.vm.network "forwarded_port", guest: 80, host: 40080, host_ip: "127.0.0.1", id: "traefik" 34 | 35 | # Open App ports for access from outside the VM 36 | masterlinux.vm.network "forwarded_port", guest: 8761, host: 8761, host_ip: "127.0.0.1", id: "eureka" 37 | masterlinux.vm.network "forwarded_port", guest: 8092, host: 8092, host_ip: "127.0.0.1", id: "spring-boot-admin" 38 | masterlinux.vm.network "forwarded_port", guest: 8090, host: 8090, host_ip: "127.0.0.1", id: "weatherbackend" 39 | masterlinux.vm.network "forwarded_port", guest: 8091, host: 8091, host_ip: "127.0.0.1", id: "weatherbockend" 40 | masterlinux.vm.network "forwarded_port", guest: 8095, host: 8095, host_ip: "127.0.0.1", id: "weatherservice" 41 | end 42 | 43 | # One Worker Node with Linux 44 | config.vm.define "workerlinux" do |workerlinux| 45 | workerlinux.vm.box = "ubuntu/xenial64" 46 | workerlinux.vm.hostname = "workerlinux01" 47 | 48 | # Forwarding the port for Ansible explicitely to not run into Vagrants 'Port Collisions and Correction' 49 | # see https://www.vagrantup.com/docs/networking/forwarded_ports.html, which would lead to problems with Ansible later 50 | workerlinux.vm.network "forwarded_port", guest: 22, host: 2232, host_ip: "127.0.0.1", id: "ssh" 51 | 52 | # As to https://www.vagrantup.com/docs/multi-machine/ & https://www.vagrantup.com/docs/networking/private_network.html 53 | # we need to configure a private network, so that our machines are able to talk to one another 54 | workerlinux.vm.network "private_network", ip: "172.16.2.11" 55 | 56 | workerlinux.vm.provider :virtualbox do |virtualbox| 57 | virtualbox.name = "WorkerLinuxUbuntu" 58 | virtualbox.gui = true 59 | virtualbox.memory = 2048 60 | virtualbox.cpus = 2 61 | virtualbox.customize ["modifyvm", :id, "--ioapic", "on"] 62 | virtualbox.customize ["modifyvm", :id, "--vram", "32"] 63 | # Forward DNS resolver from host (vagrant dns) to box 64 | virtualbox.customize ["modifyvm", :id, "--natdnshostresolver1", "on"] 65 | end 66 | 67 | # Forwarding the Guest to Host ports, so that we can access it easily from outside the VM 68 | workerlinux.vm.network "forwarded_port", guest: 8080, host: 48081, host_ip: "127.0.0.1", id: "traefik_dashboard" 69 | workerlinux.vm.network "forwarded_port", guest: 80, host: 40081, host_ip: "127.0.0.1", id: "traefik" 70 | end 71 | 72 | # One Master / Manager Node with Windows Server 2016 73 | config.vm.define "masterwindows1803" do |masterwindows| 74 | masterwindows.vm.box = "windows_1803_docker_multimachine" 75 | masterwindows.vm.hostname = "masterwindows01" 76 | 77 | # Forwarding the port for Ansible explicitely to not run into Vagrants 'Port Collisions and Correction' 78 | # see https://www.vagrantup.com/docs/networking/forwarded_ports.html, which would lead to problems with Ansible later 79 | masterwindows.vm.network "forwarded_port", guest: 5986, host: 55986, host_ip: "127.0.0.1", id: "winrm-ssl" 80 | 81 | # As to https://www.vagrantup.com/docs/multi-machine/ & https://www.vagrantup.com/docs/networking/private_network.html 82 | # we need to configure a private network, so that our machines are able to talk to one another 83 | masterwindows.vm.network "private_network", ip: "172.16.2.12" 84 | 85 | masterwindows.vm.provider :virtualbox do |virtualbox| 86 | virtualbox.name = "MasterWindowsServer1803" 87 | virtualbox.gui = true 88 | virtualbox.memory = 2048 89 | virtualbox.cpus = 2 90 | # Forward DNS resolver from host (vagrant dns) to box 91 | virtualbox.customize ["modifyvm", :id, "--natdnshostresolver1", "on"] 92 | end 93 | # Forwarding the Guest to Host ports, so that we can access it easily from outside the VM 94 | masterwindows.vm.network "forwarded_port", guest: 8080, host: 48082, host_ip: "127.0.0.1", id: "traefik_dashboard" 95 | masterwindows.vm.network "forwarded_port", guest: 80, host: 40082, host_ip: "127.0.0.1", id: "traefik" 96 | 97 | # Open App ports for access from outside the VM 98 | masterwindows.vm.network "forwarded_port", guest: 8761, host: 48761, host_ip: "127.0.0.1", id: "eureka" 99 | masterwindows.vm.network "forwarded_port", guest: 8090, host: 48090, host_ip: "127.0.0.1", id: "weatherbackend" 100 | masterwindows.vm.network "forwarded_port", guest: 8091, host: 48091, host_ip: "127.0.0.1", id: "weatherbockend" 101 | masterwindows.vm.network "forwarded_port", guest: 8095, host: 48095, host_ip: "127.0.0.1", id: "weatherservice" 102 | end 103 | 104 | # One Worker Node with Windows Server 2016 105 | config.vm.define "workerwindows1803" do |workerwindows| 106 | workerwindows.vm.box = "windows_1803_docker_multimachine" 107 | workerwindows.vm.hostname = "workerwindows01" 108 | 109 | # Forwarding the port for Ansible explicitely to not run into Vagrants 'Port Collisions and Correction' 110 | # see https://www.vagrantup.com/docs/networking/forwarded_ports.html, which would lead to problems with Ansible later 111 | workerwindows.vm.network "forwarded_port", guest: 5986, host: 55996, host_ip: "127.0.0.1", id: "winrm-ssl" 112 | 113 | # As to https://www.vagrantup.com/docs/multi-machine/ & https://www.vagrantup.com/docs/networking/private_network.html 114 | # we need to configure a private network, so that our machines are able to talk to one another 115 | workerwindows.vm.network "private_network", ip: "172.16.2.13" 116 | 117 | workerwindows.vm.provider :virtualbox do |virtualbox| 118 | virtualbox.name = "WorkerWindowsServer1803" 119 | virtualbox.gui = true 120 | virtualbox.memory = 2048 121 | virtualbox.cpus = 2 122 | # Forward DNS resolver from host (vagrant dns) to box 123 | virtualbox.customize ["modifyvm", :id, "--natdnshostresolver1", "on"] 124 | end 125 | 126 | # Forwarding the Guest to Host ports, so that we can access it easily from outside the VM 127 | workerwindows.vm.network "forwarded_port", guest: 8080, host: 48083, host_ip: "127.0.0.1", id: "traefik_dashboard" 128 | workerwindows.vm.network "forwarded_port", guest: 80, host: 40083, host_ip: "127.0.0.1", id: "traefik" 129 | end 130 | 131 | end -------------------------------------------------------------------------------- /step4-windows-linux-multimachine-vagrant-docker-swarm-setup/allow-http-docker-registry.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: all 3 | 4 | tasks: 5 | - name: Template daemon.json to /etc/docker/daemon.json on Linux nodes for later Registry access 6 | template: 7 | src: "templates/daemon.j2" 8 | dest: "/etc/docker/daemon.json" 9 | become: yes 10 | when: inventory_hostname in groups['linux'] 11 | 12 | - name: Template daemon.json to C:\ProgramData\docker\config\daemon.json on Windows nodes for later Registry access 13 | win_template: 14 | src: "templates/daemon.j2" 15 | dest: "C:\\ProgramData\\docker\\config\\daemon.json" 16 | when: inventory_hostname in groups['windows'] 17 | 18 | - name: Restart Docker service on Linux nodes, so that Registry access configuration is available 19 | service: 20 | name: docker 21 | state: restarted 22 | become: yes 23 | when: inventory_hostname in groups['linux'] 24 | 25 | - name: Restart Docker service on Windows nodes, so that Registry access configuration is available 26 | win_service: 27 | name: docker 28 | state: restarted 29 | when: inventory_hostname in groups['windows'] 30 | -------------------------------------------------------------------------------- /step4-windows-linux-multimachine-vagrant-docker-swarm-setup/display-swarm-status.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Obtain Docker Swarm status 3 | win_shell: "docker node ls" 4 | register: overview_result 5 | ignore_errors: yes 6 | when: inventory_hostname == "masterwindows01" 7 | 8 | - name: Swarm initialized... 9 | debug: 10 | msg: 11 | - "The status of the Swarm now is:" 12 | - "{{overview_result.stdout_lines}}" 13 | when: inventory_hostname == "masterwindows01" 14 | 15 | - name: Obtain currently running Docker Swarm services 16 | win_shell: "docker service ls" 17 | register: services_result 18 | ignore_errors: yes 19 | when: inventory_hostname == "masterwindows01" 20 | 21 | - name: Swarm initialized... 22 | debug: 23 | msg: 24 | - "The following Docker Swarm services are currently running (you may also check out Portainer Swarm visualizer at http://localhost:49000/ on your Vagrant host):" 25 | - "{{services_result.stdout_lines}}" 26 | when: inventory_hostname == "masterwindows01" -------------------------------------------------------------------------------- /step4-windows-linux-multimachine-vagrant-docker-swarm-setup/group_vars/all.yml: -------------------------------------------------------------------------------- 1 | ansible_user: vagrant 2 | -------------------------------------------------------------------------------- /step4-windows-linux-multimachine-vagrant-docker-swarm-setup/group_vars/linux.yml: -------------------------------------------------------------------------------- 1 | ansible_connection: ssh 2 | 3 | # Ubuntu 16.04 comes without Python 2, so one gets errors like "Shared connection to 127.0.0.1 closed.\r\n", "module_stdout": "/bin/sh: 1: /usr/bin/python: not found\r\n", 4 | # as Python 3 is already there, we´re switching over to it (see http://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html#list-of-behavioral-inventory-parameters) 5 | ansible_python_interpreter: /usr/bin/python3 6 | -------------------------------------------------------------------------------- /step4-windows-linux-multimachine-vagrant-docker-swarm-setup/group_vars/masterlinux.yml: -------------------------------------------------------------------------------- 1 | ansible_port: 2222 2 | 3 | # By default (config.ssh.insert_key is defaulting to true, even if unset) Vagrant generates a new Keypair and places the private key 4 | # inside .vagrant/machines/default/virtualbox/private_key & automatically copies the public key to /home/vagrant/.ssh/authorized_keys 5 | # the path should remain stable, but if it changes, just check with `vagrant ssh-config` on commandline 6 | ansible_ssh_private_key_file: .vagrant/machines/masterlinux/virtualbox/private_key -------------------------------------------------------------------------------- /step4-windows-linux-multimachine-vagrant-docker-swarm-setup/group_vars/masterwindows.yml: -------------------------------------------------------------------------------- 1 | ansible_port: 55986 -------------------------------------------------------------------------------- /step4-windows-linux-multimachine-vagrant-docker-swarm-setup/group_vars/windows.yml: -------------------------------------------------------------------------------- 1 | ansible_password: vagrant 2 | 3 | # http://docs.ansible.com/ansible/intro_windows.html#windows-how-does-it-work 4 | ansible_connection: winrm 5 | 6 | # The following is necessary for Python 2.7.9+ when using default WinRM self-signed certificates: 7 | ansible_winrm_server_cert_validation: ignore 8 | 9 | # to avoid time out errors like 'Read timed out. (read timeout=30)', we raise the timeout generally 10 | # see https://github.com/ansible/ansible-modules-core/issues/5368 11 | ansible_winrm_read_timeout_sec: 40 -------------------------------------------------------------------------------- /step4-windows-linux-multimachine-vagrant-docker-swarm-setup/group_vars/workerlinux.yml: -------------------------------------------------------------------------------- 1 | ansible_port: 2232 2 | 3 | # By default (config.ssh.insert_key is defaulting to true, even if unset) Vagrant generates a new Keypair and places the private key 4 | # inside .vagrant/machines/default/virtualbox/private_key & automatically copies the public key to /home/vagrant/.ssh/authorized_keys 5 | # the path should remain stable, but if it changes, just check with `vagrant ssh-config` on commandline 6 | ansible_ssh_private_key_file: .vagrant/machines/workerlinux/virtualbox/private_key -------------------------------------------------------------------------------- /step4-windows-linux-multimachine-vagrant-docker-swarm-setup/group_vars/workerwindows.yml: -------------------------------------------------------------------------------- 1 | ansible_port: 55996 -------------------------------------------------------------------------------- /step4-windows-linux-multimachine-vagrant-docker-swarm-setup/hostsfile: -------------------------------------------------------------------------------- 1 | [masterwindows] 2 | masterwindows01 3 | 4 | [masterlinux] 5 | masterlinux01 6 | 7 | [workerwindows] 8 | workerwindows01 9 | 10 | [workerlinux] 11 | workerlinux01 12 | 13 | [linux:children] 14 | masterlinux 15 | workerlinux 16 | 17 | [windows:children] 18 | masterwindows 19 | workerwindows -------------------------------------------------------------------------------- /step4-windows-linux-multimachine-vagrant-docker-swarm-setup/initialize-docker-swarm.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: all 3 | vars: 4 | masterwindows_ip: 172.16.2.12 5 | 6 | tasks: 7 | - name: Checking Ansible connectivity to Windows nodes 8 | win_ping: 9 | when: inventory_hostname in groups['windows'] 10 | 11 | - name: Checking Ansible connectivity to Linux nodes 12 | ping: 13 | when: inventory_hostname in groups['linux'] 14 | 15 | - name: Open Ports in firewalls needed for Docker Swarm 16 | include_tasks: prepare-firewalls-for-swarm.yml 17 | 18 | - name: Initialize Swarm and join all Swarm nodes 19 | include_tasks: initialize-swarm-and-join-all-nodes.yml 20 | 21 | - name: Label underlying operation system to each node 22 | include_tasks: label-os-specific-nodes.yml 23 | 24 | - name: Run Portainer as Docker and Docker Swarm Visualizer 25 | include_tasks: run-portainer.yml 26 | 27 | - name: Run Docker Swarm local Registry 28 | include_tasks: run-swarm-registry.yml 29 | 30 | - name: Display the current Docker Swarm status 31 | include_tasks: display-swarm-status.yml -------------------------------------------------------------------------------- /step4-windows-linux-multimachine-vagrant-docker-swarm-setup/initialize-swarm-and-join-all-nodes.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Leave Swarm on Windows master node, if there was a cluster before 3 | win_shell: "docker swarm leave --force" 4 | ignore_errors: yes 5 | when: inventory_hostname == "masterwindows01" 6 | 7 | - name: Initialize Docker Swarm cluster on Windows master node 8 | win_shell: "docker swarm init --advertise-addr={{masterwindows_ip}} --listen-addr {{masterwindows_ip}}:2377" 9 | ignore_errors: yes 10 | when: inventory_hostname == "masterwindows01" 11 | 12 | - name: Pause a few seconds after new Swarm cluster initialization to prevent later errors on obtaining tokens to early 13 | pause: 14 | seconds: 5 15 | 16 | - name: Obtain worker join-token from Windows master node 17 | win_shell: "docker swarm join-token worker -q" 18 | register: worker_token_result 19 | ignore_errors: yes 20 | when: inventory_hostname == "masterwindows01" 21 | 22 | - name: Obtain manager join-token from Windows master node 23 | win_shell: "docker swarm join-token manager -q" 24 | register: manager_token_result 25 | ignore_errors: yes 26 | when: inventory_hostname == "masterwindows01" 27 | 28 | - name: Syncing the worker and manager join-token results to the other hosts 29 | set_fact: 30 | worker_token_result_host_sync: "{{ hostvars['masterwindows01']['worker_token_result'] }}" 31 | manager_token_result_host_sync: "{{ hostvars['masterwindows01']['manager_token_result'] }}" 32 | 33 | - name: Extracting and saving worker and manager join-tokens in variables for joining other nodes later 34 | set_fact: 35 | worker_jointoken: "{{worker_token_result_host_sync.stdout.splitlines()[0]}}" 36 | manager_jointoken: "{{manager_token_result_host_sync.stdout.splitlines()[0]}}" 37 | 38 | - name: Join-tokens... 39 | debug: 40 | msg: 41 | - "The worker join-token is: '{{worker_jointoken}}'" 42 | - "The manager join-token is: '{{manager_jointoken}}'" 43 | 44 | - name: Leave Swarm on Windows worker nodes, if there was a cluster before 45 | win_shell: "docker swarm leave" 46 | ignore_errors: yes 47 | when: inventory_hostname in groups['workerwindows'] 48 | 49 | - name: Add Windows worker nodes to Docker Swarm cluster 50 | win_shell: "docker swarm join --token {{worker_jointoken}} {{masterwindows_ip}}" 51 | ignore_errors: yes 52 | when: inventory_hostname in groups['workerwindows'] 53 | 54 | - name: Leave Swarm on Linux worker nodes, if there was a cluster before 55 | shell: "docker swarm leave" 56 | ignore_errors: yes 57 | when: inventory_hostname in groups['workerlinux'] 58 | 59 | - name: Add Linux worker nodes to Docker Swarm cluster 60 | shell: "docker swarm join --token {{worker_jointoken}} {{masterwindows_ip}}" 61 | ignore_errors: yes 62 | when: inventory_hostname in groups['workerlinux'] 63 | 64 | - name: Leave Swarm on Linux manager nodes, if there was a cluster before 65 | shell: "docker swarm leave --force" 66 | ignore_errors: yes 67 | when: inventory_hostname in groups['masterlinux'] 68 | 69 | - name: Add Linux manager nodes to Docker Swarm cluster 70 | shell: "docker swarm join --token {{manager_jointoken}} {{masterwindows_ip}}" 71 | ignore_errors: yes 72 | when: inventory_hostname in groups['masterlinux'] 73 | -------------------------------------------------------------------------------- /step4-windows-linux-multimachine-vagrant-docker-swarm-setup/label-os-specific-nodes.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Label OS specific nodes for later mixed-OS deployments (masterwindows01 = windows) 3 | win_shell: "docker node update --label-add os=windows masterwindows01" 4 | ignore_errors: yes 5 | when: inventory_hostname == "masterwindows01" 6 | 7 | - name: Label OS specific nodes for later mixed-OS deployments (workerwindows01 = windows) 8 | win_shell: "docker node update --label-add os=windows workerwindows01" 9 | ignore_errors: yes 10 | when: inventory_hostname == "masterwindows01" 11 | 12 | - name: Label OS specific nodes for later mixed-OS deployments (workerlinux01 = linux) 13 | win_shell: "docker node update --label-add os=linux workerlinux01" 14 | ignore_errors: yes 15 | when: inventory_hostname == "masterwindows01" 16 | 17 | - name: Label OS specific nodes for later mixed-OS deployments (masterlinux01 = linux) 18 | win_shell: "docker node update --label-add os=linux masterlinux01" 19 | ignore_errors: yes 20 | when: inventory_hostname == "masterwindows01" 21 | -------------------------------------------------------------------------------- /step4-windows-linux-multimachine-vagrant-docker-swarm-setup/playbookCommands.sh: -------------------------------------------------------------------------------- 1 | # Prepare Docker on all Cluster nodes 2 | ansible-playbook -i hostsfile prepare-docker-nodes.yml 3 | 4 | # Only prepare base image springboot-oraclejre-nanoserver 5 | ansible-playbook -i hostsfile prepare-docker-nodes.yml --tags "baseimage" 6 | 7 | # Leave out newer Docker installation 8 | ansible-playbook -i hostsfile prepare-docker-nodes.yml --skip-tags "dockerinstall" 9 | 10 | # Initialize Docker Swarm 11 | ansible-playbook -i hostsfile initialize-docker-swarm.yml 12 | 13 | -------------------------------------------------------------------------------- /step4-windows-linux-multimachine-vagrant-docker-swarm-setup/prepare-docker-linux.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: "{{host}}" 3 | become: true 4 | gather_facts: true 5 | 6 | pre_tasks: 7 | - name: update apt and autoremove 8 | apt: 9 | update_cache: yes 10 | cache_valid_time: 3600 11 | autoremove: yes 12 | 13 | tasks: 14 | - name: Add Docker apt key 15 | apt_key: 16 | url: https://download.docker.com/linux/ubuntu/gpg 17 | id: 9DC858229FC7DD38854AE2D88D81803C0EBFCD88 18 | state: present 19 | register: add_repository_key 20 | ignore_errors: true 21 | 22 | - name: Add docker apt repo 23 | apt_repository: 24 | repo: "deb [arch=amd64] https://download.docker.com/linux/ubuntu {{ansible_lsb.codename}} edge" 25 | update_cache: yes 26 | become: true 27 | 28 | - name: Install Docker apt package 29 | apt: 30 | pkg: docker-ce 31 | state: latest 32 | update_cache: yes 33 | become: true 34 | 35 | - name: Ensure Docker service is installed and restarted 36 | service: 37 | name: docker 38 | state: restarted 39 | enabled: yes 40 | 41 | - name: Install pip 42 | apt: 43 | name: python3-pip 44 | state: latest 45 | 46 | - name: Install Docker Compose 47 | pip: 48 | name: docker-compose 49 | 50 | - name: Add vagrant user to docker group. 51 | user: 52 | name: vagrant 53 | groups: docker 54 | append: yes 55 | become: true -------------------------------------------------------------------------------- /step4-windows-linux-multimachine-vagrant-docker-swarm-setup/prepare-docker-nodes.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: all 3 | 4 | tasks: 5 | - name: Checking Ansible connectivity to Windows nodes 6 | win_ping: 7 | when: inventory_hostname in groups['windows'] 8 | 9 | - name: Checking Ansible connectivity to Linux nodes 10 | ping: 11 | when: inventory_hostname in groups['linux'] 12 | 13 | - name: Prepare Docker on Windows nodes 14 | import_playbook: "../step1-prepare-docker-windows/prepare-docker-windows.yml host=windows" 15 | 16 | - name: Prepare Docker on Linux nodes 17 | import_playbook: prepare-docker-linux.yml host=linux 18 | 19 | - name: Allow local http Docker registry 20 | import_playbook: allow-http-docker-registry.yml 21 | -------------------------------------------------------------------------------- /step4-windows-linux-multimachine-vagrant-docker-swarm-setup/prepare-firewalls-for-swarm.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Allow Ping requests on Windows nodes (which is by default disabled in Windows Server 2016) 3 | win_firewall_rule: 4 | name: Allow incoming ping requests 5 | action: allow 6 | direction: in 7 | protocol: "icmpv4:8" 8 | state: present 9 | enabled: yes 10 | when: inventory_hostname in groups['windows'] 11 | 12 | - name: Allow connection to TCP port 2377 for cluster management communications 13 | win_firewall_rule: 14 | name: Port 2377 15 | localport: 2377 16 | action: allow 17 | direction: in 18 | protocol: tcp 19 | state: present 20 | enabled: yes 21 | when: inventory_hostname in groups['masterwindows'] 22 | 23 | # Container networking needs more open ports later, see https://docs.docker.com/engine/swarm/ingress/ 24 | - name: Open ports for later Docker Swarm Container network discovery on TCP and UDP port 7946 25 | win_firewall_rule: 26 | name: Port 7946 27 | localport: 7946 28 | action: allow 29 | direction: in 30 | protocol: tcp 31 | state: present 32 | enabled: yes 33 | when: inventory_hostname in groups['windows'] 34 | 35 | - name: Open ports for later Docker Swarm Container network discovery on UDP port 4789 36 | win_firewall_rule: 37 | name: Port 4789 38 | localport: 4789 39 | action: allow 40 | direction: in 41 | protocol: udp 42 | state: present 43 | enabled: yes 44 | when: inventory_hostname in groups['windows'] 45 | 46 | # temporarily disabling the complete firewall to prevent issues 47 | - name: Disable firewall for Domain, Public and Private profiles 48 | win_firewall: 49 | state: disabled 50 | profiles: 51 | - Domain 52 | - Private 53 | - Public 54 | when: inventory_hostname in groups['windows'] 55 | tags: disable_firewall -------------------------------------------------------------------------------- /step4-windows-linux-multimachine-vagrant-docker-swarm-setup/run-portainer.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Create directory for later volume mount into Portainer service on Linux Manager node, if it doesn´t exist 3 | file: 4 | path: /mnt/portainer 5 | state: directory 6 | mode: 0755 7 | when: inventory_hostname in groups['linux'] 8 | become: true 9 | 10 | - name: Run Portainer Docker and Docker Swarm Visualizer on Linux Manager node as Swarm service 11 | shell: "docker service create --detach --name portainer --publish 9000:9000 --constraint 'node.role == manager' --constraint 'node.labels.os==linux' --mount type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock --mount type=bind,src=/mnt/portainer,dst=/data portainer/portainer:latest -H unix:///var/run/docker.sock" 12 | ignore_errors: yes 13 | when: inventory_hostname == "masterlinux01" 14 | -------------------------------------------------------------------------------- /step4-windows-linux-multimachine-vagrant-docker-swarm-setup/run-swarm-registry.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Specify to run Docker Registry on Linux Manager node 3 | shell: "docker node update --label-add registry=true masterlinux01" 4 | ignore_errors: yes 5 | when: inventory_hostname == "masterlinux01" 6 | 7 | - name: Create directory for later volume mount into the Docker Registry service on Linux Manager node, if it doesn´t exist 8 | file: 9 | path: /mnt/registry 10 | state: directory 11 | mode: 0755 12 | when: inventory_hostname in groups['linux'] 13 | become: true 14 | 15 | - name: Run Docker Registry on Linux Manager node as Swarm service 16 | shell: "docker service create --detach --name swarm-registry --constraint 'node.labels.registry==true' --mount type=bind,src=/mnt/registry,dst=/var/lib/registry -e REGISTRY_HTTP_ADDR=0.0.0.0:5000 -p 5000:5000 --replicas 1 registry:2" 17 | ignore_errors: yes 18 | when: inventory_hostname == "masterlinux01" 19 | -------------------------------------------------------------------------------- /step4-windows-linux-multimachine-vagrant-docker-swarm-setup/templates/daemon.j2: -------------------------------------------------------------------------------- 1 | { 2 | "insecure-registries" : ["172.16.2.10:5000"] 3 | } -------------------------------------------------------------------------------- /step5-deploy-multiple-spring-boot-apps-to-mixed-os-docker-swarm/build-and-deploy-apps-2-swarm.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: all 3 | vars: 4 | application_stack_name: clearsky 5 | registry_host: 172.16.2.10:5000 6 | swarm_network_name: mixed_swarm_net 7 | docker_domain: masterlinux01.test 8 | base_path_windows: "C:\\springboot" 9 | base_path_linux: "/tmp/springboot" 10 | services: 11 | 12 | - name: eureka-serviceregistry 13 | path_to_jar: "../../cxf-spring-cloud-netflix-docker/eureka-serviceregistry/target/eureka-serviceregistry-0.0.1-SNAPSHOT.jar" 14 | port: 8761 15 | service_registry_name: eureka-serviceregistry 16 | deploy_target: linux 17 | replicas: 1 18 | 19 | - name: spring-boot-admin 20 | path_to_jar: "../../cxf-spring-cloud-netflix-docker/spring-boot-admin/target/spring-boot-admin-0.0.1-SNAPSHOT.jar" 21 | port: 8092 22 | service_registry_name: eureka-serviceregistry 23 | deploy_target: windows 24 | replicas: 1 25 | 26 | - name: weatherbackend 27 | path_to_jar: "../../cxf-spring-cloud-netflix-docker/weatherbackend/target/weatherbackend-0.0.1-SNAPSHOT.jar" 28 | port: 8090 29 | service_registry_name: eureka-serviceregistry 30 | deploy_target: linux 31 | replicas: 2 32 | 33 | - name: weatherbockend 34 | path_to_jar: "../../cxf-spring-cloud-netflix-docker/weatherbackend/target/weatherbackend-0.0.1-SNAPSHOT.jar" 35 | port: 8091 36 | service_registry_name: eureka-serviceregistry 37 | deploy_target: windows 38 | replicas: 2 39 | 40 | - name: weatherservice 41 | path_to_jar: "../../cxf-spring-cloud-netflix-docker/weatherservice/target/weatherservice-0.0.1-SNAPSHOT.jar" 42 | port: 8095 43 | service_registry_name: eureka-serviceregistry 44 | deploy_target: windows 45 | replicas: 2 46 | 47 | tasks: 48 | 49 | - name: Create Docker build directory /tmp/springboot on Linux manager node, if not there 50 | file: 51 | path: "{{base_path_linux}}" 52 | state: directory 53 | mode: 0755 54 | when: inventory_hostname == "masterlinux01" 55 | tags: buildapps 56 | 57 | - name: Create Docker build directory C:\springboot on Windows manager node, if not there 58 | win_file: 59 | path: "{{base_path_windows}}" 60 | state: directory 61 | when: inventory_hostname == "masterwindows01" 62 | tags: buildapps 63 | 64 | - name: Build Linux Apps Docker images on Linux manager node and push to Docker Swarm registry 65 | include_tasks: prepare-docker-images-linux.yml 66 | with_items: "{{ vars.services }}" 67 | when: inventory_hostname == "masterlinux01" and item.deploy_target == 'linux' 68 | tags: buildapps 69 | 70 | - name: Build Windows Apps Docker images on Windows manager node and push to Docker Swarm registry 71 | include_tasks: prepare-docker-images-windows.yml 72 | with_items: "{{ vars.services }}" 73 | when: inventory_hostname == "masterwindows01" and item.deploy_target == 'windows' 74 | tags: buildapps 75 | 76 | - name: Open all published ports of every app on every node for later access from outside the Swarm 77 | include_tasks: prepare-firewall-app-access.yml 78 | with_items: "{{ vars.services }}" 79 | tags: firewall 80 | 81 | - name: Deploy the Stack to the Swarm on Windows Manager node 82 | include_tasks: deploy-services-swarm.yml 83 | when: inventory_hostname == "masterwindows01" 84 | tags: deploy 85 | 86 | - name: Display the current Docker Swarm status 87 | include_tasks: ../step4-windows-linux-multimachine-vagrant-docker-swarm-setup/display-swarm-status.yml 88 | 89 | # - name: Do healthchecks for all services 90 | # include_tasks: spring-boot-app-health-check.yml 91 | # with_items: "{{ vars.services }}" -------------------------------------------------------------------------------- /step5-deploy-multiple-spring-boot-apps-to-mixed-os-docker-swarm/deploy-services-swarm.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Template docker-stack.yml to directory C:\spring-boot 3 | win_template: 4 | src: "templates/docker-stack.j2" 5 | dest: "{{base_path_windows}}\\docker-stack.yml" 6 | 7 | - name: Remove old Stack from the Swarm, if there 8 | win_shell: docker stack rm {{ application_stack_name }} 9 | args: 10 | chdir: "{{base_path_windows}}" 11 | ignore_errors: yes 12 | 13 | - name: Delete old Swarm overlay network 14 | win_shell: "docker network rm {{swarm_network_name}}" 15 | ignore_errors: yes 16 | 17 | - name: Pause a few seconds after old Stack removement 18 | pause: 19 | seconds: 2 20 | 21 | - name: Create an overlay network to enable our Swarm services to connect to each other later on 22 | win_shell: "docker network create --driver=overlay {{swarm_network_name}}" 23 | ignore_errors: yes 24 | 25 | - name: Give the Swarm a few seconds to add all peers to the new network 26 | pause: 27 | seconds: 4 28 | 29 | - name: Deploy the Stack to the Swarm on Windows Manager node 30 | win_shell: docker stack deploy --compose-file docker-stack.yml {{ application_stack_name }} 31 | args: 32 | chdir: "{{base_path_windows}}" 33 | ignore_errors: yes 34 | -------------------------------------------------------------------------------- /step5-deploy-multiple-spring-boot-apps-to-mixed-os-docker-swarm/group_vars/all.yml: -------------------------------------------------------------------------------- 1 | ansible_user: vagrant 2 | -------------------------------------------------------------------------------- /step5-deploy-multiple-spring-boot-apps-to-mixed-os-docker-swarm/group_vars/linux.yml: -------------------------------------------------------------------------------- 1 | ansible_connection: ssh 2 | 3 | # Ubuntu 16.04 comes without Python 2, so one gets errors like "Shared connection to 127.0.0.1 closed.\r\n", "module_stdout": "/bin/sh: 1: /usr/bin/python: not found\r\n", 4 | # as Python 3 is already there, we´re switching over to it (see http://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html#list-of-behavioral-inventory-parameters) 5 | ansible_python_interpreter: /usr/bin/python3 6 | -------------------------------------------------------------------------------- /step5-deploy-multiple-spring-boot-apps-to-mixed-os-docker-swarm/group_vars/masterlinux.yml: -------------------------------------------------------------------------------- 1 | ansible_port: 2222 2 | 3 | # By default (config.ssh.insert_key is defaulting to true, even if unset) Vagrant generates a new Keypair and places the private key 4 | # inside .vagrant/machines/default/virtualbox/private_key & automatically copies the public key to /home/vagrant/.ssh/authorized_keys 5 | # the path should remain stable, but if it changes, just check with `vagrant ssh-config` on commandline 6 | ansible_ssh_private_key_file: ../step4-windows-linux-multimachine-vagrant-docker-swarm-setup/.vagrant/machines/masterlinux/virtualbox/private_key -------------------------------------------------------------------------------- /step5-deploy-multiple-spring-boot-apps-to-mixed-os-docker-swarm/group_vars/masterwindows.yml: -------------------------------------------------------------------------------- 1 | ansible_port: 55986 -------------------------------------------------------------------------------- /step5-deploy-multiple-spring-boot-apps-to-mixed-os-docker-swarm/group_vars/windows.yml: -------------------------------------------------------------------------------- 1 | ansible_password: vagrant 2 | 3 | # http://docs.ansible.com/ansible/intro_windows.html#windows-how-does-it-work 4 | ansible_connection: winrm 5 | 6 | # The following is necessary for Python 2.7.9+ when using default WinRM self-signed certificates: 7 | ansible_winrm_server_cert_validation: ignore 8 | 9 | # to avoid time out errors like 'Read timed out. (read timeout=30)', we raise the timeout generally 10 | # see https://github.com/ansible/ansible-modules-core/issues/5368 11 | ansible_winrm_read_timeout_sec: 40 -------------------------------------------------------------------------------- /step5-deploy-multiple-spring-boot-apps-to-mixed-os-docker-swarm/group_vars/workerlinux.yml: -------------------------------------------------------------------------------- 1 | ansible_port: 2232 2 | 3 | # By default (config.ssh.insert_key is defaulting to true, even if unset) Vagrant generates a new Keypair and places the private key 4 | # inside .vagrant/machines/default/virtualbox/private_key & automatically copies the public key to /home/vagrant/.ssh/authorized_keys 5 | # the path should remain stable, but if it changes, just check with `vagrant ssh-config` on commandline 6 | ansible_ssh_private_key_file: ../step4-windows-linux-multimachine-vagrant-docker-swarm-setup/.vagrant/machines/workerlinux/virtualbox/private_key -------------------------------------------------------------------------------- /step5-deploy-multiple-spring-boot-apps-to-mixed-os-docker-swarm/group_vars/workerwindows.yml: -------------------------------------------------------------------------------- 1 | ansible_port: 55996 -------------------------------------------------------------------------------- /step5-deploy-multiple-spring-boot-apps-to-mixed-os-docker-swarm/hostsfile: -------------------------------------------------------------------------------- 1 | [masterwindows] 2 | masterwindows01 3 | 4 | [masterlinux] 5 | masterlinux01 6 | 7 | [workerwindows] 8 | workerwindows01 9 | 10 | [workerlinux] 11 | workerlinux01 12 | 13 | [linux:children] 14 | masterlinux 15 | workerlinux 16 | 17 | [windows:children] 18 | masterwindows 19 | workerwindows -------------------------------------------------------------------------------- /step5-deploy-multiple-spring-boot-apps-to-mixed-os-docker-swarm/playbookCommands.sh: -------------------------------------------------------------------------------- 1 | # Build all Applications docker images and deploy to Swarm 2 | ansible-playbook -i hostsfile build-and-deploy-apps-2-swarm.yml 3 | 4 | # Just deploy all Applications to Swarm (they have to been build once before that will work out) 5 | ansible-playbook -i hostsfile build-and-deploy-apps-2-swarm.yml --skip-tags "buildapps" 6 | 7 | # Only open Firewall ports for Apps 8 | ansible-playbook -i hostsfile build-and-deploy-apps-2-swarm.yml --skip-tags="deploy,buildapps" 9 | 10 | -------------------------------------------------------------------------------- /step5-deploy-multiple-spring-boot-apps-to-mixed-os-docker-swarm/prepare-docker-images-linux.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Defining needed variables 3 | set_fact: 4 | spring_boot_app: 5 | name: "{{ item.name }}" 6 | port: "{{ item.port }}" 7 | jar: "{{ item.path_to_jar }}" 8 | registry_name: "{{ item.service_registry_name }}" 9 | 10 | - name: Preparing the following Spring Boot App´s Docker build files 11 | debug: 12 | msg: "Processing '{{spring_boot_app.name}}' with port '{{ spring_boot_app.port }}' on {{ item.deploy_target }}" 13 | 14 | - name: Create directory /tmp/springboot/spring_boot_app.name, if not there 15 | file: 16 | path: "{{base_path_linux}}/{{spring_boot_app.name}}" 17 | state: directory 18 | mode: 0755 19 | 20 | - name: Template and copy Spring Boot app´s Dockerfile to directory /tmp/springboot/spring_boot_app.name 21 | template: 22 | src: "templates/Dockerfile-SpringBoot-Linux.j2" 23 | dest: "{{base_path_linux}}/{{spring_boot_app.name}}/Dockerfile" 24 | 25 | - name: Copy Spring Boot app´s jar-File to directory /tmp/springboot/spring_boot_app.name 26 | copy: 27 | src: "{{spring_boot_app.jar}}" 28 | dest: "{{base_path_linux}}/{{spring_boot_app.name}}/{{spring_boot_app.name}}.jar" 29 | 30 | - name: Remove existing App´s Docker Container image 31 | shell: "docker rmi {{registry_host}}/{{spring_boot_app.name}}:latest --force" 32 | ignore_errors: yes 33 | 34 | - name: Build the Service´ Docker image 35 | shell: "docker build . --tag {{registry_host}}/{{spring_boot_app.name}}:latest" 36 | args: 37 | chdir: "{{base_path_linux}}/{{spring_boot_app.name}}" 38 | 39 | - name: Push the Docker Container image to the Swarm Registry 40 | shell: "docker push {{registry_host}}/{{spring_boot_app.name}}:latest" 41 | 42 | -------------------------------------------------------------------------------- /step5-deploy-multiple-spring-boot-apps-to-mixed-os-docker-swarm/prepare-docker-images-windows.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Defining needed variables 3 | set_fact: 4 | spring_boot_app: 5 | name: "{{ item.name }}" 6 | port: "{{ item.port }}" 7 | jar: "{{ item.path_to_jar }}" 8 | registry_name: "{{ item.service_registry_name }}" 9 | 10 | - name: Preparing the following Spring Boot App´s Docker build files 11 | debug: 12 | msg: "Processing '{{spring_boot_app.name}}' with port '{{ spring_boot_app.port }}' on {{ item.deploy_target }}" 13 | 14 | - name: Create directory C:\springboot\spring_boot_app.name, if not there 15 | win_file: 16 | path: "{{base_path_windows}}\\{{spring_boot_app.name}}" 17 | state: directory 18 | 19 | - name: Template and copy Spring Boot app´s Dockerfile to directory C:\springboot\spring_boot_app.name 20 | win_template: 21 | src: "templates/Dockerfile-SpringBoot-Windows.j2" 22 | dest: "{{base_path_windows}}\\{{spring_boot_app.name}}\\Dockerfile" 23 | 24 | - name: Copy Spring Boot app´s jar-File to directory C:\springboot\spring_boot_app.name 25 | win_copy: 26 | src: "{{spring_boot_app.jar}}" 27 | dest: "{{base_path_windows}}\\{{spring_boot_app.name}}\\{{spring_boot_app.name}}.jar" 28 | 29 | - name: Remove existing App´s Docker Container image 30 | win_shell: "docker rmi {{registry_host}}/{{spring_boot_app.name}}:latest --force" 31 | ignore_errors: yes 32 | 33 | - name: Build the App´s Docker Container image 34 | win_shell: "docker build . --tag {{registry_host}}/{{spring_boot_app.name}}:latest" 35 | args: 36 | chdir: "{{base_path_windows}}\\{{spring_boot_app.name}}" 37 | 38 | - name: Push the Docker Container image to the Swarm Registry 39 | win_shell: "docker push {{registry_host}}/{{spring_boot_app.name}}:latest" 40 | -------------------------------------------------------------------------------- /step5-deploy-multiple-spring-boot-apps-to-mixed-os-docker-swarm/prepare-firewall-app-access.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Preparing to open... 3 | debug: 4 | msg: "'{{ item.name }}' with port '{{ item.port }}'" 5 | 6 | - name: Open the apps published port on Linux node for later access from outside the Swarm 7 | ufw: 8 | rule: allow 9 | port: "{{ item.port }}" 10 | proto: tcp 11 | comment: "{{ item.name }}s port {{ item.port }}" 12 | become: true 13 | when: inventory_hostname in groups['linux'] 14 | 15 | - name: Open the apps published port on Windows node for later access from outside the Swarm 16 | win_firewall_rule: 17 | name: "{{ item.name }}'s port {{ item.port }}" 18 | localport: "{{ item.port }}" 19 | action: allow 20 | direction: in 21 | protocol: tcp 22 | state: present 23 | enabled: yes 24 | when: inventory_hostname in groups['windows'] 25 | -------------------------------------------------------------------------------- /step5-deploy-multiple-spring-boot-apps-to-mixed-os-docker-swarm/spring-boot-app-health-check.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Defining needed variables 3 | set_fact: 4 | spring_boot_app: 5 | name: "{{ item.name }}" 6 | port: "{{ item.port }}" 7 | 8 | - name: Obtain the Docker Container´s internal IP address (because localhost doesn´t work for now https://github.com/docker/for-win/issues/458) 9 | win_shell: "docker inspect -f {% raw %}'{{ .NetworkSettings.Networks.nat.IPAddress }}' {% endraw %} springboot_{{spring_boot_app.name}}_1 {{ '>' }} container_ip.txt" 10 | 11 | - name: Get the Docker Container´s internal IP address from the temporary txt-file (we have to do this because of templating problems, see http://stackoverflow.com/a/32279729/4964553) 12 | win_shell: cat container_ip.txt 13 | register: win_shell_txt_return 14 | 15 | - name: Define the IP as variable 16 | set_fact: 17 | docker_container_ip: "{{ win_shell_txt_return.stdout.splitlines()[0] }}" 18 | 19 | - debug: 20 | msg: "The Docker Container that runs your App '{{spring_boot_app.name}}' has the internal IP {{ docker_container_ip }} --> Let´s do a health-check against this URI: 'http://{{ docker_container_ip }}:{{spring_boot_app.port}}/health'" 21 | 22 | # Spring Boot Actuators strange Content-Type 'application/vnd.spring-boot.actuator.v1+json' when calling 23 | # http://appname:port/health can be avoided by using the a correct header: 'Accept: application/json' 24 | # Doing so, the app reacts with a normal 'application/json' in the response and the healthcheck run's fine again :) 25 | - name: Wait until our Spring Boot app is up & running 26 | win_uri: 27 | url: "http://{{ docker_container_ip }}:{{spring_boot_app.port}}/health" 28 | method: GET 29 | headers: 30 | Accept: application/json 31 | register: health_result 32 | until: health_result.status_code == 200 33 | retries: 30 34 | delay: 20 35 | ignore_errors: yes 36 | 37 | - name: Show some more info, only when health check went wrong 38 | win_uri: 39 | url: "http://{{ docker_container_ip }}:{{spring_boot_app.port}}/health" 40 | method: GET 41 | register: health_bad_result 42 | ignore_errors: yes 43 | when: health_result|failed 44 | 45 | - name: Show some more info, only when health check went wrong 46 | debug: 47 | msg: "The app reacted with: {{health_bad_result}}" 48 | when: health_result|failed 49 | 50 | -------------------------------------------------------------------------------- /step5-deploy-multiple-spring-boot-apps-to-mixed-os-docker-swarm/templates/Dockerfile-SpringBoot-Linux.j2: -------------------------------------------------------------------------------- 1 | FROM openjdk:8-jdk-alpine 2 | 3 | MAINTAINER Jonas Hecht 4 | 5 | VOLUME /tmp 6 | 7 | ENV REGISTRY_HOST {{spring_boot_app.registry_name}} 8 | ENV SPRINGBOOT_APP_NAME {{spring_boot_app.name}} 9 | 10 | # Add Spring Boot app.jar to Container 11 | ADD {{spring_boot_app.name}}.jar app.jar 12 | 13 | ENV JAVA_OPTS="" 14 | 15 | # Fire up our Spring Boot app by default 16 | ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar --server.port={{spring_boot_app.port}}" ] -------------------------------------------------------------------------------- /step5-deploy-multiple-spring-boot-apps-to-mixed-os-docker-swarm/templates/Dockerfile-SpringBoot-Windows.j2: -------------------------------------------------------------------------------- 1 | #jinja2: newline_sequence:'\r\n' 2 | FROM springboot-oraclejre-nanoserver:latest 3 | 4 | MAINTAINER Jonas Hecht 5 | 6 | ENV REGISTRY_HOST {{spring_boot_app.registry_name}} 7 | ENV SPRINGBOOT_APP_NAME {{spring_boot_app.name}} 8 | 9 | # Add Spring Boot app.jar to Container 10 | ADD {{spring_boot_app.name}}.jar app.jar 11 | 12 | # Fire up our Spring Boot app by default 13 | CMD ["java.exe", "-jar app.jar --server.port={{spring_boot_app.port}}"] -------------------------------------------------------------------------------- /step5-deploy-multiple-spring-boot-apps-to-mixed-os-docker-swarm/templates/docker-stack.j2: -------------------------------------------------------------------------------- 1 | #jinja2: newline_sequence:'\r\n' 2 | version: '3.4' 3 | 4 | services: 5 | 6 | {% for service in vars.services %} 7 | {{ service.name }}: 8 | image: {{registry_host}}/{{ service.name }} 9 | ports: 10 | - target: {{ service.port }} 11 | published: {{ service.port }} 12 | protocol: tcp 13 | tty: 14 | true 15 | restart: 16 | unless-stopped 17 | deploy: 18 | endpoint_mode: vip 19 | replicas: {{ service.replicas }} 20 | placement: 21 | {% if service.deploy_target == 'windows' %} 22 | constraints: [node.labels.os==windows] 23 | {% else %} 24 | constraints: [node.labels.os==linux] 25 | {% endif %} 26 | labels: 27 | - "traefik.port={{ service.port }}" 28 | - "traefik.docker.network={{ swarm_network_name }}" 29 | - "traefik.backend={{ service.name }}" 30 | # Use Traefik healthcheck "traefik.backend.healthcheck.path": "/healthcheck", 31 | - "traefik.frontend.rule=Host:{{ service.name }}.{{ docker_domain }}" 32 | 33 | {% endfor %} 34 | 35 | traefik: 36 | image: traefik 37 | ports: 38 | - target: 80 39 | published: 80 40 | protocol: tcp 41 | - target: 8080 42 | published: 8080 43 | protocol: tcp 44 | tty: 45 | true 46 | restart: 47 | unless-stopped 48 | deploy: 49 | replicas: 1 50 | placement: 51 | constraints: [node.labels.os==linux] 52 | constraints: [node.role == manager] 53 | command: 54 | - --docker 55 | - --docker.swarmmode 56 | - --docker.domain={{ docker_domain }} 57 | - --docker.watch 58 | - --web 59 | - --logLevel=INFO 60 | volumes: 61 | - type: bind 62 | source: /var/run/docker.sock 63 | target: /var/run/docker.sock 64 | 65 | networks: 66 | default: 67 | external: 68 | name: {{ swarm_network_name }} --------------------------------------------------------------------------------