diff --git a/openstackclient/compute/v2/server.py b/openstackclient/compute/v2/server.py
index ea87d9cea1..a0afa389f6 100644
--- a/openstackclient/compute/v2/server.py
+++ b/openstackclient/compute/v2/server.py
@@ -575,14 +575,17 @@ class CreateServer(command.ShowOne):
             # NOTE(RuiChen): Add '\n' at the end of line to put each item in
             #                the separated line, avoid the help message looks
             #                messy, see _SmartHelpFormatter in cliff.
+            # FIXME(mriedem): Technically <id> can be the name or ID.
             help=_('Create a block device on the server.\n'
                    'Block device mapping in the format\n'
                    '<dev-name>=<id>:<type>:<size(GB)>:<delete-on-terminate>\n'
                    '<dev-name>: block device name, like: vdb, xvdc '
                    '(required)\n'
-                   '<id>: UUID of the volume or snapshot (required)\n'
-                   '<type>: volume or snapshot; default: volume (optional)\n'
-                   '<size(GB)>: volume size if create from snapshot '
+                   '<id>: UUID of the volume, volume snapshot or image '
+                   '(required)\n'
+                   '<type>: volume, snapshot or image; default: volume '
+                   '(optional)\n'
+                   '<size(GB)>: volume size if create from image or snapshot '
                    '(optional)\n'
                    '<delete-on-terminate>: true or false; default: false '
                    '(optional)\n'
@@ -793,7 +796,7 @@ class CreateServer(command.ShowOne):
                 mapping = {'device_name': dev_name}
                 # 1. decide source and destination type
                 if (len(dev_map) > 1 and
-                        dev_map[1] in ('volume', 'snapshot')):
+                        dev_map[1] in ('volume', 'snapshot', 'image')):
                     mapping['source_type'] = dev_map[1]
                 else:
                     mapping['source_type'] = 'volume'
@@ -808,14 +811,29 @@ class CreateServer(command.ShowOne):
                     snapshot_id = utils.find_resource(
                         volume_client.volume_snapshots, dev_map[0]).id
                     mapping['uuid'] = snapshot_id
+                elif mapping['source_type'] == 'image':
+                    # NOTE(mriedem): In case --image is specified with the same
+                    # image, that becomes the root disk for the server. If the
+                    # block device is specified with a root device name, e.g.
+                    # vda, then the compute API will likely fail complaining
+                    # that there is a conflict. So if using the same image ID,
+                    # which doesn't really make sense but it's allowed, the
+                    # device name would need to be a non-root device, e.g. vdb.
+                    # Otherwise if the block device image is different from the
+                    # one specified by --image, then the compute service will
+                    # create a volume from the image and attach it to the
+                    # server as a non-root volume.
+                    image_id = utils.find_resource(
+                        image_client.images, dev_map[0]).id
+                    mapping['uuid'] = image_id
                 # 3. append size and delete_on_termination if exist
                 if len(dev_map) > 2 and dev_map[2]:
                     mapping['volume_size'] = dev_map[2]
                 if len(dev_map) > 3 and dev_map[3]:
                     mapping['delete_on_termination'] = dev_map[3]
             else:
-                msg = _("Volume or snapshot (name or ID) must be specified if "
-                        "--block-device-mapping is specified")
+                msg = _("Volume, volume snapshot or image (name or ID) must "
+                        "be specified if --block-device-mapping is specified")
                 raise exceptions.CommandError(msg)
             block_device_mapping_v2.append(mapping)
 
diff --git a/openstackclient/tests/functional/compute/v2/test_server.py b/openstackclient/tests/functional/compute/v2/test_server.py
index e52a42d3a1..67e2a66ef8 100644
--- a/openstackclient/tests/functional/compute/v2/test_server.py
+++ b/openstackclient/tests/functional/compute/v2/test_server.py
@@ -614,6 +614,93 @@ class ServerTests(common.ComputeTestCase):
             # the attached volume had been deleted
             pass
 
+    def test_server_boot_with_bdm_image(self):
+        # Tests creating a server where the root disk is backed by the given
+        # --image but a --block-device-mapping with type=image is provided so
+        # that the compute service creates a volume from that image and
+        # attaches it as a non-root volume on the server. The block device is
+        # marked as delete_on_termination=True so it will be automatically
+        # deleted when the server is deleted.
+
+        # create server with bdm type=image
+        # NOTE(mriedem): This test is a bit unrealistic in that specifying the
+        # same image in the block device as the --image option does not really
+        # make sense, but we just want to make sure everything is processed
+        # as expected where nova creates a volume from the image and attaches
+        # that volume to the server.
+        server_name = uuid.uuid4().hex
+        server = json.loads(self.openstack(
+            'server create -f json ' +
+            '--flavor ' + self.flavor_name + ' ' +
+            '--image ' + self.image_name + ' ' +
+            '--block-device-mapping '
+            # This means create a 1GB volume from the specified image, attach
+            # it to the server at /dev/vdb and delete the volume when the
+            # server is deleted.
+            'vdb=' + self.image_name + ':image:1:true ' +
+            self.network_arg + ' ' +
+            '--wait ' +
+            server_name
+        ))
+        self.assertIsNotNone(server["id"])
+        self.assertEqual(
+            server_name,
+            server['name'],
+        )
+        self.wait_for_status(server_name, 'ACTIVE')
+
+        # check server volumes_attached, format is
+        # {"volumes_attached": "id='2518bc76-bf0b-476e-ad6b-571973745bb5'",}
+        cmd_output = json.loads(self.openstack(
+            'server show -f json ' +
+            server_name
+        ))
+        volumes_attached = cmd_output['volumes_attached']
+        self.assertTrue(volumes_attached.startswith('id='))
+        attached_volume_id = volumes_attached.replace('id=', '')
+
+        # check the volume that attached on server
+        cmd_output = json.loads(self.openstack(
+            'volume show -f json ' +
+            attached_volume_id
+        ))
+        attachments = cmd_output['attachments']
+        self.assertEqual(
+            1,
+            len(attachments),
+        )
+        self.assertEqual(
+            server['id'],
+            attachments[0]['server_id'],
+        )
+        self.assertEqual(
+            "in-use",
+            cmd_output['status'],
+        )
+        # TODO(mriedem): If we can parse the volume_image_metadata field from
+        # the volume show output we could assert the image_name is what we
+        # specified. volume_image_metadata is something like this:
+        # {u'container_format': u'bare', u'min_ram': u'0',
+        # u'disk_format': u'qcow2', u'image_name': u'cirros-0.4.0-x86_64-disk',
+        # u'image_id': u'05496c83-e2df-4c2f-9e48-453b6e49160d',
+        # u'checksum': u'443b7623e27ecf03dc9e01ee93f67afe', u'min_disk': u'0',
+        # u'size': u'12716032'}
+
+        # delete server, then check the attached volume has been deleted
+        self.openstack('server delete --wait ' + server_name)
+        cmd_output = json.loads(self.openstack(
+            'volume list -f json'
+        ))
+        target_volume = [each_volume
+                         for each_volume in cmd_output
+                         if each_volume['ID'] == attached_volume_id]
+        if target_volume:
+            # check the attached volume is 'deleting' status
+            self.assertEqual('deleting', target_volume[0]['Status'])
+        else:
+            # the attached volume had been deleted
+            pass
+
     def test_server_create_with_none_network(self):
         """Test server create with none network option."""
         server_name = uuid.uuid4().hex
diff --git a/releasenotes/notes/story-2006302-support-bdm-type-image-0becfb63bd4fb969.yaml b/releasenotes/notes/story-2006302-support-bdm-type-image-0becfb63bd4fb969.yaml
new file mode 100644
index 0000000000..6e8e8ba0b8
--- /dev/null
+++ b/releasenotes/notes/story-2006302-support-bdm-type-image-0becfb63bd4fb969.yaml
@@ -0,0 +1,8 @@
+---
+features:
+  - |
+    The ``server create --block-device-mapping`` option now supports
+    an ``image`` type in addition to ``volume`` and ``snapshot``. When
+    specifying an image block device the compute service will create a volume
+    from the image of the specified size and attach it to the server.
+    [Story `2006302 <https://storyboard.openstack.org/#!/story/2006302>`_]