diff --git a/ansible/kolla-host.yml b/ansible/kolla-host.yml
index e0b9bec9be..fb55075e30 100644
--- a/ansible/kolla-host.yml
+++ b/ansible/kolla-host.yml
@@ -33,7 +33,8 @@
 
 - name: Apply role baremetal
   hosts: baremetal
-  gather_facts: no
+  serial: '{{ kolla_serial|default("0") }}'
+  gather_facts: false
   roles:
     - { role: baremetal,
         tags: baremetal }
diff --git a/ansible/roles/baremetal/defaults/main.yml b/ansible/roles/baremetal/defaults/main.yml
index 332d27cd15..c65e530cff 100644
--- a/ansible/roles/baremetal/defaults/main.yml
+++ b/ansible/roles/baremetal/defaults/main.yml
@@ -1,10 +1,52 @@
 ---
-docker_apt_url: "{{ 'http://obs.linaro.org/ERP:/17.12/Debian_9' if ansible_architecture == 'aarch64' else 'https://apt.dockerproject.org' }}"
-docker_apt_key_file: "{{ 'Release.key' if ansible_architecture == 'aarch64' else 'gpg' }}"
-docker_apt_key_id: "{{ 'C32DA102AD89C2BE' if ansible_architecture == 'aarch64' else 'F76221572C52609D' }}"
+# Whether to enable a package repository for Docker.
+enable_docker_repo: true
 
-docker_yum_url: "https://yum.dockerproject.org"
-docker_gpg_fingerprint: "58118E89F3A912897C070ADBF76221572C52609D"
+# Whether to use the legacy Docker packages at dockerproject.org instead of the
+# newer packages at docker.com.
+docker_legacy_packages: false
+
+# Docker APT repository configuration.
+docker_apt_url: "{% if docker_legacy_packages | bool %}{{ docker_legacy_apt_url }}{% else %}{{ docker_new_apt_url }}{% endif %}"
+docker_apt_repo: "{% if docker_legacy_packages | bool %}{{ docker_legacy_apt_repo }}{% else %}{{ docker_new_apt_repo }}{% endif %}"
+docker_apt_key_file: "{% if docker_legacy_packages | bool %}{{ docker_legacy_apt_key_file }}{% else %}{{ docker_new_apt_key_file }}{% endif %}"
+docker_apt_key_id: "{% if docker_legacy_packages | bool %}{{ docker_legacy_apt_key_id }}{% else %}{{ docker_new_apt_key_id }}{% endif %}"
+docker_apt_package: "{% if docker_legacy_packages | bool %}{{ docker_legacy_apt_package }}{% else %}{{ docker_new_apt_package }}{% endif %}"
+
+# Docker APT repository configuration when docker_legacy_packages is false.
+docker_new_apt_url: "https://download.docker.com/linux/{{ ansible_distribution | lower }}"
+docker_new_apt_repo: "deb {{ docker_new_apt_url }} {{ ansible_lsb.codename }} stable"
+docker_new_apt_key_file: "gpg"
+docker_new_apt_key_id: "0EBFCD88"
+docker_new_apt_package: "docker-ce"
+
+# Docker APT repository configuration when docker_legacy_packages is true.
+docker_legacy_apt_url: "{{ 'http://obs.linaro.org/ERP:/17.12/Debian_9' if ansible_architecture == 'aarch64' else 'https://apt.dockerproject.org' }}"
+docker_legacy_apt_repo: "{{ docker_legacy_apt_repo_aarch64 if ansible_architecture == 'aarch64' else docker_legacy_apt_repo_x86_64 }}"
+docker_legacy_apt_repo_x86_64: "deb {{ docker_apt_url }}/repo {{ ansible_distribution | lower }}-{{ ansible_distribution_release | lower }} main"
+docker_legacy_apt_repo_aarch64: "deb {{ docker_apt_url }} ./"
+docker_legacy_apt_key_file: "{{ 'Release.key' if ansible_architecture == 'aarch64' else 'gpg' }}"
+docker_legacy_apt_key_id: "{{ 'C32DA102AD89C2BE' if ansible_architecture == 'aarch64' else 'F76221572C52609D' }}"
+docker_legacy_apt_package: "{{ 'docker-ce' if ansible_architecture == 'aarch64' else 'docker-engine=1.12.*' }}"
+
+# Docker Yum repository configuration.
+docker_yum_url: "{% if docker_legacy_packages | bool %}{{ docker_legacy_yum_url }}{% else %}{{ docker_new_yum_url }}{% endif %}"
+docker_yum_baseurl: "{% if docker_legacy_packages | bool %}{{ docker_legacy_yum_baseurl }}{% else %}{{ docker_new_yum_baseurl }}{% endif %}"
+docker_yum_gpgkey: "{% if docker_legacy_packages | bool %}{{ docker_legacy_yum_gpgkey }}{% else %}{{ docker_new_yum_gpgkey }}{% endif %}"
+docker_yum_gpgcheck: true
+docker_yum_package: "{% if docker_legacy_packages | bool %}{{ docker_legacy_yum_package }}{% else %}{{ docker_new_yum_package }}{% endif %}"
+
+# Docker Yum repository configuration when docker_legacy_packages is false.
+docker_new_yum_url: "https://download.docker.com/linux/{{ ansible_distribution | lower }}"
+docker_new_yum_baseurl: "{{ docker_yum_url }}/{{ ansible_distribution_major_version | lower }}/$basearch/stable"
+docker_new_yum_gpgkey: "{{ docker_yum_url }}/gpg"
+docker_new_yum_package: "docker-ce"
+
+# Docker Yum repository configuration when docker_legacy_packages is true.
+docker_legacy_yum_url: "https://yum.dockerproject.org"
+docker_legacy_yum_baseurl: "{{ docker_legacy_yum_url }}/repo/main/{{ ansible_distribution | lower }}/{{ ansible_distribution_major_version | lower }}"
+docker_legacy_yum_gpgkey: "{{ docker_legacy_yum_url }}/gpg"
+docker_legacy_yum_package: "docker-engine-1.12.0"
 
 customize_etc_hosts: True
 
@@ -27,14 +69,14 @@ docker_custom_option: ""
 docker_runtime_directory: ""
 
 debian_pkg_install:
- - "{{ 'docker-ce' if ansible_architecture == 'aarch64' else 'docker-engine=1.12.*' }}"
+ - "{{ docker_apt_package }}"
  - git
  - python-setuptools
  - ntp
 
 redhat_pkg_install:
  - epel-release
- - docker-engine-1.12.0
+ - "{{ docker_yum_package }}"
  - git
  - python-setuptools
  - ntp
diff --git a/ansible/roles/baremetal/tasks/install.yml b/ansible/roles/baremetal/tasks/install.yml
index 92519df73d..8cf7137fa1 100644
--- a/ansible/roles/baremetal/tasks/install.yml
+++ b/ansible/roles/baremetal/tasks/install.yml
@@ -5,6 +5,12 @@
   become: True
   when: ansible_os_family == 'Debian'
 
+- name: Update yum cache
+  yum:
+    update_cache: yes
+  become: True
+  when: ansible_os_family == 'RedHat'
+
 # TODO(inc0): Gates don't seem to have ufw executable, check for it instead of ignore errors
 - name: Set firewall default policy
   become: True
@@ -32,6 +38,17 @@
     - ansible_os_family == 'RedHat'
     - firewalld_check.rc == 0
 
+# Upgrading docker engine may cause containers to stop. Take a snapshot of the
+# running containers prior to a potential upgrade of Docker.
+
+- name: Check which containers are running
+  command: docker ps -f 'status=running' -q
+  become: true
+  # If Docker is not installed this command may exit non-zero.
+  failed_when: false
+  changed_when: false
+  register: running_containers
+
 - name: Install apt packages
   package:
     name: "{{ item }}"
@@ -39,6 +56,7 @@
   become: True
   with_items: "{{ debian_pkg_install }}"
   when: ansible_os_family == 'Debian'
+  register: apt_install_result
 
 - name: Install deltarpm packages
   package:
@@ -56,6 +74,30 @@
   become: True
   with_items: "{{ redhat_pkg_install }}"
   when: ansible_os_family == 'RedHat'
+  register: yum_install_result
+
+# If any packages were updated, and any containers were running, wait for the
+# daemon to come up and start all previously running containers.
+
+- block:
+    - name: Wait for Docker to start
+      command: docker info
+      become: true
+      changed_when: false
+      register: result
+      until: result is success
+      retries: 6
+      delay: 10
+
+    - name: Ensure containers are running after Docker upgrade
+      command: "docker start {{ running_containers.stdout }}"
+      become: true
+  when:
+    - install_result is changed
+    - running_containers.rc == 0
+    - running_containers.stdout != ''
+  vars:
+    install_result: "{{ yum_install_result if ansible_os_family == 'RedHat' else apt_install_result }}"
 
 - name: Install virtualenv packages
   package:
@@ -94,7 +136,9 @@
     state: absent
   with_items: "{{ ubuntu_pkg_removals }}"
   become: True
-  when: ansible_distribution|lower == "ubuntu"
+  when:
+    - ansible_distribution|lower == "ubuntu"
+    - item != ""
 
 - name: Remove packages
   package:
@@ -102,4 +146,6 @@
     state: absent
   with_items: "{{ redhat_pkg_removals }}"
   become: True
-  when: ansible_os_family == 'RedHat'
+  when:
+    - ansible_os_family == 'RedHat'
+    - item != ""
diff --git a/ansible/roles/baremetal/tasks/pre-install.yml b/ansible/roles/baremetal/tasks/pre-install.yml
index 8e5065646f..f67300ed67 100644
--- a/ansible/roles/baremetal/tasks/pre-install.yml
+++ b/ansible/roles/baremetal/tasks/pre-install.yml
@@ -47,64 +47,65 @@
   become: True
   when: create_kolla_user | bool
 
-- name: Install apt packages
-  apt:
-    update_cache: yes
-  become: True
-  when: ansible_os_family == 'Debian'
+- block:
+    - block:
+        - name: Install apt packages
+          apt:
+            update_cache: yes
+          become: True
 
-- name: Install ca certs
-  package:
-    name: "{{ item }}"
-    state: latest
-  become: True
-  with_items:
-    - ca-certificates
-    - apt-transport-https
-  when:
-    - ansible_os_family == 'Debian'
+        - name: Install ca certs
+          package:
+            name: "{{ item }}"
+            state: latest
+          become: True
+          with_items:
+            - ca-certificates
+            - apt-transport-https
 
-- name: Ensure apt sources list directory exists
-  file:
-    path: /etc/apt/sources.list.d
-    state: directory
-    recurse: yes
-  become: True
-  when: ansible_os_family == 'Debian'
+        - name: Ensure apt sources list directory exists
+          file:
+            path: /etc/apt/sources.list.d
+            state: directory
+            recurse: yes
+          become: True
 
-- name: Enable docker repo apt
-  template:
-    src: docker_apt_repo.j2
-    dest: /etc/apt/sources.list.d/docker.list
-  become: True
-  when: ansible_os_family == 'Debian'
+        - name: Install docker apt gpg key
+          apt_key:
+            url: "{{ docker_apt_url }}/{{ docker_apt_key_file }}"
+            id: "{{ docker_apt_key_id }}"
+            state: present
+          become: True
 
-- name: Install docker apt gpg key
-  apt_key:
-    url: "{{ docker_apt_url }}/{{ docker_apt_key_file }}"
-    id: "{{ docker_apt_key_id }}"
-    state: present
-  become: True
-  when: ansible_os_family == 'Debian'
+        - name: Enable docker apt repository
+          apt_repository:
+            repo: "{{ docker_apt_repo }}"
+            filename: docker
+          become: True
+      when: ansible_os_family == 'Debian'
 
-- name: Ensure yum repos directory exists
-  file:
-    path: /etc/yum.repos.d/
-    state: directory
-    recurse: yes
-  become: True
-  when: ansible_os_family == 'RedHat'
+    - block:
+        - name: Ensure yum repos directory exists
+          file:
+            path: /etc/yum.repos.d/
+            state: directory
+            recurse: yes
+          become: True
 
-- name: Enable docker repo yum
-  become: True
-  template:
-    src: docker_yum_repo.j2
-    dest: /etc/yum.repos.d/docker.repo
-  when: ansible_os_family == 'RedHat'
+        - name: Enable docker yum repository
+          yum_repository:
+            name: docker
+            description: Docker main Repository
+            baseurl: "{{ docker_yum_baseurl }}"
+            gpgcheck: "{{ docker_yum_gpgcheck | bool }}"
+            gpgkey: "{{ docker_yum_gpgkey }}"
+          become: True
 
-- name: Install docker rpm gpg key
-  rpm_key:
-    state: present
-    key: "{{ docker_yum_url }}/gpg"
-  become: True
-  when: ansible_os_family == 'RedHat'
+        - name: Install docker rpm gpg key
+          rpm_key:
+            state: present
+            key: "{{ docker_yum_url }}/gpg"
+          become: True
+          when: docker_yum_gpgcheck | bool
+      when: ansible_os_family == 'RedHat'
+  when: enable_docker_repo | bool
diff --git a/ansible/roles/baremetal/templates/docker_apt_repo.j2 b/ansible/roles/baremetal/templates/docker_apt_repo.j2
deleted file mode 100644
index 326f1824f8..0000000000
--- a/ansible/roles/baremetal/templates/docker_apt_repo.j2
+++ /dev/null
@@ -1,6 +0,0 @@
-{% if ansible_architecture == 'aarch64' %}
-deb {{ docker_apt_url }} ./
-{% else %}
-# main docker repo
-deb {{ docker_apt_url }}/repo {{ ansible_distribution | lower }}-{{ ansible_distribution_release | lower }} main
-{% endif %}
diff --git a/ansible/roles/baremetal/templates/docker_yum_repo.j2 b/ansible/roles/baremetal/templates/docker_yum_repo.j2
deleted file mode 100644
index 8de5f3703c..0000000000
--- a/ansible/roles/baremetal/templates/docker_yum_repo.j2
+++ /dev/null
@@ -1,6 +0,0 @@
-[docker-repo]
-name=Docker main Repository
-baseurl={{ docker_yum_url }}/repo/main/{{ ansible_distribution | lower }}/{{ ansible_distribution_major_version | lower }}
-enabled=1
-gpgcheck=1
-gpgkey={{ docker_yum_url }}/gpg
diff --git a/releasenotes/notes/docker-ce-722582da41cf6cd3.yaml b/releasenotes/notes/docker-ce-722582da41cf6cd3.yaml
new file mode 100644
index 0000000000..9fcbdf8868
--- /dev/null
+++ b/releasenotes/notes/docker-ce-722582da41cf6cd3.yaml
@@ -0,0 +1,23 @@
+---
+features:
+  - |
+    Adds support for installing Docker Community Edition (CE) using the
+    ``kolla-ansible bootstrap-servers`` command.  Existing support uses the
+    legacy packages from https://dockerproject.org.  New packages are
+    distributed via https://download.docker.com, and that location is now
+    supported and used by default.  Use of the legacy packages is enabled by
+    setting the variable ``docker_legacy_packages`` to ``true``.
+
+    It is also now possible to skip configuration of the Docker repository, by
+    setting the variable ``enable_docker_repo`` to ``false``.
+upgrade:
+  - |
+    The default value for ``docker_legacy_packages`` is ``false``, which means
+    that the Docker Community Edition (CE) should be installed. If the
+    ``kolla-ansible bootstrap-servers`` command is used on a previously
+    deployed host that is running a legacy Docker engine, it would result in
+    the Docker engine being upgraded to use the Docker Community Edition
+    packages, which will result in a restart of the Docker engine and the
+    containers running on that host.  Use the ``kolla-ansible`` ``--serial`` or
+    ``--limit`` arguments to avoid losing quorum in clustered services such as
+    MariaDB by restarting all containers at once.
diff --git a/tests/run.yml b/tests/run.yml
index 04554b16eb..6714347348 100644
--- a/tests/run.yml
+++ b/tests/run.yml
@@ -98,7 +98,7 @@
 
     - name: create deamon.json for nodepool cache
       vars:
-        infra_dockerhub_mirror: "http://{{ zuul_site_mirror_fqdn }}:8081/registry-1.docker/"
+        infra_dockerhub_mirror: "http://{{ zuul_site_mirror_fqdn }}:8082/"
       template:
         src: "{{ kolla_ansible_full_src_dir }}/tests/templates/docker_daemon.json.j2"
         dest: "/etc/docker/daemon.json"