Docker Community Forums

Share and learn in the Docker community.

Manage each new layer in a similar way as transactions commits

Each command in Dockerfile creates a new layer, so the best practice is to minimize them and to combine somehow, if it is possible.

The question is: can we manage this behavour in a similar way as transactions commits . With sql script, if you run DML statements like:

insert into ...
update ...

Each of them is commited immediately (in case autocommit is enable). You can wrap them and apply as a single transaction. With docker each command creates a new layer (also we can say, that each command is commited).

Instead of special hacks how to combine docker commands, I’d like to be able to control it. Something like:

FROM ...


RUN ...
COPY ...
RUN ...


Probably it has been already requested and declined. If not, what do you think of it.

1 Like

// This function takes arguments for 2 connection strings and commands to create a transaction
// involving two SQL Servers. It returns a value > 0 if the transaction is committed, 0 if the
// transaction is rolled back. To test this code, you can connect to two different databases
// on the same server by altering the connection string, or to another 3rd party RDBMS by
// altering the code in the connection2 code block.
static public int CreateTransactionScope(
string connectString1, string connectString2,
string commandText1, string commandText2)
// Initialize the return value to zero and create a StringWriter to display results.
int returnValue = 0;
System.IO.StringWriter writer = new System.IO.StringWriter();

    // Create the TransactionScope to execute the commands, guaranteeing
    // that both commands can commit or roll back as a single unit of work.
    using (TransactionScope scope = new TransactionScope())
        using (SqlConnection connection1 = new SqlConnection(connectString1))
            // Opening the connection automatically enlists it in the
            // TransactionScope as a lightweight transaction.

            // Create the SqlCommand object and execute the first command.
            SqlCommand command1 = new SqlCommand(commandText1, connection1);
            returnValue = command1.ExecuteNonQuery();
            writer.WriteLine("Rows to be affected by command1: {0}", returnValue);

            // If you get here, this means that command1 succeeded. By nesting
            // the using block for connection2 inside that of connection1, you
            // conserve server and network resources as connection2 is opened
            // only when there is a chance that the transaction can commit.
            using (SqlConnection connection2 = new SqlConnection(connectString2))
                // The transaction is escalated to a full distributed
                // transaction when connection2 is opened.

                // Execute the second command in the second database.
                returnValue = 0;
                SqlCommand command2 = new SqlCommand(commandText2, connection2);
                returnValue = command2.ExecuteNonQuery();
                writer.WriteLine("Rows to be affected by command2: {0}", returnValue);

        // The Complete method commits the transaction. If an exception has been thrown,
        // Complete is not  called and the transaction is rolled back.
catch (TransactionAbortedException ex)
    writer.WriteLine("TransactionAbortedException Message: {0}", ex.Message);

// Display messages.

return returnValue;


This issue is not about, how to support transactions at all. The issue is about creating a new layer in the same way, as we can control transactions and commits in sql.
To simplify Dockerfile creation. Now we are forced to apply certain workarounds to reduce a number of layers.